Add the Grafana observability suite (#961)

* Add the Grafana observability suite

* Update configs

* Update docker script directory structure

* Fix the otel trace id

* Add grafana ini

* Fix some configs and loguru integration

* Add the celery grafana

* Update Grafana dashboards

* Update configs

* Fix issues with the panel

* Update grafana configs

* Update grafana dashboards

* Optimized panel styles

* Add sqlalchemy traces

* Fix the CORS

* Update the grafana query and config

* Update grafana status is off by default
This commit is contained in:
Wu Clan
2025-12-15 17:06:43 +08:00
committed by GitHub
parent 6b4fd93e5f
commit 4bc5ba53e6
28 changed files with 5282 additions and 34 deletions

View File

@@ -36,14 +36,14 @@ COPY --from=builder /fba /fba
COPY --from=builder /usr/local /usr/local
COPY deploy/backend/supervisord.conf /etc/supervisor/supervisord.conf
COPY deploy/backend/supervisor/supervisord.conf /etc/supervisor/supervisord.conf
WORKDIR /fba/backend
# === FastAPI server image ===
FROM base_server AS fba_server
COPY deploy/backend/fba_server.conf /etc/supervisor/conf.d/
COPY deploy/backend/supervisor/fba_server.conf /etc/supervisor/conf.d/
RUN mkdir -p /var/log/fba
@@ -54,7 +54,7 @@ CMD ["supervisord", "-c", "/etc/supervisor/supervisord.conf"]
# === Celery Worker image ===
FROM base_server AS fba_celery_worker
COPY deploy/backend/fba_celery_worker.conf /etc/supervisor/conf.d/
COPY deploy/backend/supervisor/fba_celery_worker.conf /etc/supervisor/conf.d/
RUN mkdir -p /var/log/fba
@@ -63,7 +63,7 @@ CMD ["supervisord", "-c", "/etc/supervisor/supervisord.conf"]
# === Celery Beat image ===
FROM base_server AS fba_celery_beat
COPY deploy/backend/fba_celery_beat.conf /etc/supervisor/conf.d/
COPY deploy/backend/supervisor/fba_celery_beat.conf /etc/supervisor/conf.d/
RUN mkdir -p /var/log/fba
@@ -72,7 +72,7 @@ CMD ["supervisord", "-c", "/etc/supervisor/supervisord.conf"]
# === Celery Flower image ===
FROM base_server AS fba_celery_flower
COPY deploy/backend/fba_celery_flower.conf /etc/supervisor/conf.d/
COPY deploy/backend/supervisor/fba_celery_flower.conf /etc/supervisor/conf.d/
RUN mkdir -p /var/log/fba

View File

@@ -52,6 +52,8 @@ def init_celery() -> celery.Celery:
task_track_started=True,
enable_utc=False,
timezone=settings.DATETIME_TIMEZONE,
worker_send_task_events=True,
task_send_sent_event=True,
)
# 在 Celery 中设置此参数无效

View File

@@ -2,6 +2,7 @@ from fastapi import FastAPI, Request
from fastapi.exceptions import RequestValidationError
from pydantic import ValidationError
from starlette.exceptions import HTTPException
from starlette.middleware.cors import CORSMiddleware
from uvicorn.protocols.http.h11_impl import STATUS_PHRASES
from backend.common.context import ctx
@@ -75,7 +76,7 @@ async def _validation_exception_handler(exc: RequestValidationError | Validation
return MsgSpecJSONResponse(status_code=StandardResponseCode.HTTP_422, content=content)
def register_exception(app: FastAPI) -> None:
def register_exception(app: FastAPI) -> None: # noqa: C901
@app.exception_handler(HTTPException)
async def http_exception_handler(request: Request, exc: HTTPException):
"""
@@ -194,3 +195,55 @@ def register_exception(app: FastAPI) -> None:
status_code=StandardResponseCode.HTTP_500,
content=content,
)
if settings.MIDDLEWARE_CORS:
@app.exception_handler(StandardResponseCode.HTTP_500)
async def cors_custom_code_500_exception_handler(request: Request, exc: BaseExceptionError | Exception):
"""
跨域自定义 500 异常处理
:param request: FastAPI 请求对象
:param exc: 自定义异常
:return:
"""
if isinstance(exc, BaseExceptionError):
content = {
'code': exc.code,
'msg': exc.msg,
'data': exc.data,
}
else:
if settings.ENVIRONMENT == 'dev':
content = {
'code': StandardResponseCode.HTTP_500,
'msg': str(exc),
'data': None,
}
else:
res = response_base.fail(res=CustomResponseCode.HTTP_500)
content = res.model_dump()
content.update(trace_id=get_request_trace_id())
response = MsgSpecJSONResponse(
status_code=exc.code if isinstance(exc, BaseExceptionError) else StandardResponseCode.HTTP_500,
content=content,
background=exc.background if isinstance(exc, BaseExceptionError) else None,
)
origin = request.headers.get('origin')
if origin:
cors = CORSMiddleware(
app=app,
allow_origins=settings.CORS_ALLOWED_ORIGINS,
allow_credentials=True,
allow_methods=['*'],
allow_headers=['*'],
expose_headers=settings.CORS_EXPOSE_HEADERS,
)
response.headers.update(cors.simple_headers)
has_cookie = 'cookie' in request.headers
if cors.allow_all_origins and has_cookie:
response.headers['Access-Control-Allow-Origin'] = origin
elif not cors.allow_all_origins and cors.is_allowed_origin(origin=origin):
response.headers['Access-Control-Allow-Origin'] = origin
response.headers.add_vary_header('Origin')
return response

View File

@@ -47,6 +47,13 @@ def default_formatter(record: logging.LogRecord) -> str:
return settings.LOG_FORMAT if settings.LOG_FORMAT.endswith('\n') else f'{settings.LOG_FORMAT}\n'
def request_id_filter(record: logging.LogRecord) -> logging.LogRecord:
"""请求 ID 过滤器"""
rid = get_request_trace_id()
record['request_id'] = rid[: settings.TRACE_ID_LOG_LENGTH]
return record
def setup_logging() -> None:
"""
设置日志处理器
@@ -75,12 +82,6 @@ def setup_logging() -> None:
# 移除 loguru 默认处理器
logger.remove()
# request_id 过滤器
def request_id_filter(record: logging.LogRecord) -> logging.LogRecord:
rid = get_request_trace_id()
record['request_id'] = rid[: settings.TRACE_ID_LOG_LENGTH]
return record
# 配置 loguru 处理器
logger.configure(
handlers=[

View File

View File

@@ -0,0 +1,35 @@
from prometheus_client import Counter, Gauge, Histogram
from backend.core.conf import settings
PROMETHEUS_INFO_GAUGE = (
Gauge(name='fba_app_info', documentation='fba 应用信息', labelnames=['app_name'])
.labels(app_name=settings.GRAFANA_APP_NAME)
.inc()
)
PROMETHEUS_REQUEST_IN_PROGRESS_GAUGE = Gauge(
'fba_request_in_progress',
'按方法和路径统计请求的衡量',
['app_name', 'method', 'path'],
)
PROMETHEUS_REQUEST_COUNTER = Counter('fba_request_total', '按方法和路径统计请求总数', ['app_name', 'method', 'path'])
PROMETHEUS_RESPONSE_COUNTER = Counter(
'fba_response_total',
'按方法、路径和状态码统计响应总数',
['app_name', 'method', 'path', 'status_code'],
)
PROMETHEUS_EXCEPTION_COUNTER = Counter(
'fba_exception_total',
'按方法,路径和异常类型统计异常总数',
['app_name', 'method', 'path', 'exception_type'],
)
PROMETHEUS_REQUEST_COST_TIME_HISTOGRAM = Histogram(
'fba_request_cost_time',
'按方法和路径划分请求耗时的直方图(以 ms 为单位)',
['app_name', 'method', 'path'],
)

View File

@@ -23,7 +23,7 @@ class Settings(BaseSettings):
# FastAPI
FASTAPI_API_V1_PATH: str = '/api/v1'
FASTAPI_TITLE: str = 'FastAPI'
FASTAPI_TITLE: str = 'fba'
FASTAPI_DESCRIPTION: str = 'FastAPI Best Architecture'
FASTAPI_DOCS_URL: str = '/docs'
FASTAPI_REDOC_URL: str = '/redoc'
@@ -215,6 +215,11 @@ class Settings(BaseSettings):
# I18n 配置
I18N_DEFAULT_LANGUAGE: str = 'zh-CN'
# Grafana
GRAFANA_METRICS: bool = False
GRAFANA_APP_NAME: str = 'fba_server'
GRAFANA_OTLP_GRPC_ENDPOINT: str = 'fba_alloy:4317'
##################################################
# [ App ] task
##################################################

View File

@@ -9,10 +9,10 @@ import socketio
from fastapi import Depends, FastAPI
from fastapi_limiter import FastAPILimiter
from fastapi_pagination import add_pagination
from prometheus_client import make_asgi_app
from starlette.middleware.authentication import AuthenticationMiddleware
from starlette.middleware.cors import CORSMiddleware
from starlette.staticfiles import StaticFiles
from starlette.types import ASGIApp
from starlette_context.middleware import ContextMiddleware
from starlette_context.plugins import RequestIdPlugin
@@ -33,8 +33,10 @@ from backend.plugin.tools import build_final_router
from backend.utils.demo_site import demo_site
from backend.utils.health_check import ensure_unique_route_names, http_limit_callback
from backend.utils.openapi import simplify_operation_ids
from backend.utils.otel import init_otel
from backend.utils.serializers import MsgSpecJSONResponse
from backend.utils.snowflake import snowflake
from backend.utils.trace_id import OtelTraceIdPlugin
@asynccontextmanager
@@ -76,22 +78,7 @@ async def register_init(app: FastAPI) -> AsyncGenerator[None, None]:
def register_app() -> FastAPI:
"""注册 FastAPI 应用"""
class MyFastAPI(FastAPI):
if settings.MIDDLEWARE_CORS:
# Related issues
# https://github.com/fastapi/fastapi/discussions/7847
# https://github.com/fastapi/fastapi/discussions/8027
def build_middleware_stack(self) -> ASGIApp:
return CORSMiddleware(
super().build_middleware_stack(),
allow_origins=settings.CORS_ALLOWED_ORIGINS,
allow_credentials=True,
allow_methods=['*'],
allow_headers=['*'],
expose_headers=settings.CORS_EXPOSE_HEADERS,
)
app = MyFastAPI(
app = FastAPI(
title=settings.FASTAPI_TITLE,
version=__version__,
description=settings.FASTAPI_DESCRIPTION,
@@ -111,6 +98,9 @@ def register_app() -> FastAPI:
register_page(app)
register_exception(app)
if settings.GRAFANA_METRICS:
register_metrics(app)
return app
@@ -164,15 +154,29 @@ def register_middleware(app: FastAPI) -> None:
app.add_middleware(AccessMiddleware)
# ContextVar
plugins = [OtelTraceIdPlugin()] if settings.GRAFANA_METRICS else [RequestIdPlugin(validate=True)]
app.add_middleware(
ContextMiddleware,
plugins=[RequestIdPlugin(validate=True)],
plugins=plugins,
default_error_response=MsgSpecJSONResponse(
content={'code': StandardResponseCode.HTTP_400, 'msg': 'BAD_REQUEST', 'data': None},
status_code=StandardResponseCode.HTTP_400,
),
)
# CORS
# https://github.com/fastapi-practices/fastapi_best_architecture/pull/789/changes
# https://github.com/open-telemetry/opentelemetry-python-contrib/issues/4031
if settings.MIDDLEWARE_CORS:
app.add_middleware(
CORSMiddleware,
allow_origins=settings.CORS_ALLOWED_ORIGINS,
allow_credentials=True,
allow_methods=['*'],
allow_headers=['*'],
expose_headers=settings.CORS_EXPOSE_HEADERS,
)
def register_router(app: FastAPI) -> None:
"""
@@ -218,3 +222,16 @@ def register_socket_app(app: FastAPI) -> None:
socketio_path='/ws/socket.io',
)
app.mount('/ws', socket_app)
def register_metrics(app: FastAPI) -> None:
"""
注册指标
:param app: FastAPI 应用实例
:return:
"""
metrics_app = make_asgi_app()
app.mount('/metrics', metrics_app)
init_otel(app)

View File

@@ -14,6 +14,13 @@ from backend.app.admin.service.opera_log_service import opera_log_service
from backend.common.context import ctx
from backend.common.enums import OperaLogCipherType, StatusType
from backend.common.log import log
from backend.common.prometheus.instruments import (
PROMETHEUS_EXCEPTION_COUNTER,
PROMETHEUS_REQUEST_COST_TIME_HISTOGRAM,
PROMETHEUS_REQUEST_COUNTER,
PROMETHEUS_REQUEST_IN_PROGRESS_GAUGE,
PROMETHEUS_RESPONSE_COUNTER,
)
from backend.common.queue import batch_dequeue
from backend.common.response.response_code import StandardResponseCode
from backend.core.conf import settings
@@ -43,6 +50,10 @@ class OperaLogMiddleware(BaseHTTPMiddleware):
else:
method = request.method
args = await self.get_request_args(request)
PROMETHEUS_REQUEST_IN_PROGRESS_GAUGE.labels(
app_name=settings.GRAFANA_APP_NAME, method=method, path=path
).inc()
PROMETHEUS_REQUEST_COUNTER.labels(app_name=settings.GRAFANA_APP_NAME, method=method, path=path).inc()
# 执行请求
code = 200
@@ -63,6 +74,12 @@ class OperaLogMiddleware(BaseHTTPMiddleware):
code = exception.get('code')
msg = exception.get('msg')
log.error(f'请求异常: {msg}')
PROMETHEUS_EXCEPTION_COUNTER.labels(
app_name=settings.GRAFANA_APP_NAME,
method=method,
path=path,
exception_type=type(e).__name__,
).inc()
break
except Exception as e:
elapsed = round((time.perf_counter() - ctx.perf_time) * 1000, 3)
@@ -71,6 +88,20 @@ class OperaLogMiddleware(BaseHTTPMiddleware):
status = StatusType.disable
error = e
log.error(f'请求异常: {e!s}')
PROMETHEUS_EXCEPTION_COUNTER.labels(
app_name=settings.GRAFANA_APP_NAME, method=method, path=path, exception_type=type(e).__name__
).inc()
else:
PROMETHEUS_REQUEST_COST_TIME_HISTOGRAM.labels(
app_name=settings.GRAFANA_APP_NAME, method=method, path=path
).observe(elapsed, exemplar={'TraceID': get_request_trace_id()})
finally:
PROMETHEUS_RESPONSE_COUNTER.labels(
app_name=settings.GRAFANA_APP_NAME, method=method, path=path, status_code=code
).inc()
PROMETHEUS_REQUEST_IN_PROGRESS_GAUGE.labels(
app_name=settings.GRAFANA_APP_NAME, method=method, path=path
).dec()
# 此信息只能在请求后获取
route = request.scope.get('route')

59
backend/utils/otel.py Normal file
View File

@@ -0,0 +1,59 @@
from fastapi import FastAPI
from opentelemetry import trace
from opentelemetry._logs import set_logger_provider
from opentelemetry.exporter.otlp.proto.grpc._log_exporter import OTLPLogExporter
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
from opentelemetry.instrumentation.logging import LoggingInstrumentor
from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor
from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler
from opentelemetry.sdk._logs._internal.export import BatchLogRecordProcessor
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from backend.common.log import log, request_id_filter
from backend.core.conf import settings
from backend.database.db import async_engine
def init_otel(app: FastAPI) -> None:
"""
初始化 OpenTelemetry
:param app: FastAPI 应用实例
:return:
"""
from backend import __version__
resource = Resource(
attributes={
'service.name': settings.GRAFANA_APP_NAME,
'service.version': __version__,
'deployment.environment': settings.ENVIRONMENT,
},
)
tracer_provider = TracerProvider(resource=resource)
trace.set_tracer_provider(tracer_provider)
span_exporter = OTLPSpanExporter(endpoint=settings.GRAFANA_OTLP_GRPC_ENDPOINT, insecure=True)
tracer_provider.add_span_processor(BatchSpanProcessor(span_exporter))
logger_provider = LoggerProvider(resource=resource)
set_logger_provider(logger_provider)
log_exporter = OTLPLogExporter(endpoint=settings.GRAFANA_OTLP_GRPC_ENDPOINT, insecure=True)
logger_provider.add_log_record_processor(BatchLogRecordProcessor(log_exporter))
otel_logging_handler = LoggingHandler(logger_provider=logger_provider)
log.add( # type: ignore
otel_logging_handler,
level=settings.LOG_STD_LEVEL,
format=settings.LOG_FORMAT,
filter=lambda record: request_id_filter(record),
)
LoggingInstrumentor().instrument(set_logging_format=True)
SQLAlchemyInstrumentor().instrument(engine=async_engine.sync_engine)
FastAPIInstrumentor.instrument_app(app, tracer_provider=tracer_provider)

View File

@@ -1,9 +1,31 @@
from typing import Any
from opentelemetry import trace
from starlette.requests import Request
from starlette_context.plugins import Plugin
from backend.common.context import ctx
from backend.core.conf import settings
def get_request_trace_id() -> str:
"""请求头中获取追踪 ID"""
"""上下文中获取追踪 ID"""
if ctx.exists():
return ctx.get(settings.TRACE_ID_REQUEST_HEADER_KEY, settings.TRACE_ID_LOG_DEFAULT_VALUE)
return settings.TRACE_ID_LOG_DEFAULT_VALUE
class OtelTraceIdPlugin(Plugin):
"""OpenTelemetry Trace ID 插件"""
key = settings.TRACE_ID_REQUEST_HEADER_KEY
async def process_request(self, request: Request) -> Any:
"""从 OpenTelemetry span 中提取 trace_id"""
span = trace.get_current_span()
span_ctx = span.get_span_context()
if span_ctx.is_valid:
return trace.format_trace_id(span_ctx.trace_id)
return settings.TRACE_ID_LOG_DEFAULT_VALUE

View File

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,158 @@
// ============================================================================
// Grafana Alloy 配置文件
// Alloy 是 Grafana 的可观测性数据收集器(原 Grafana Agent
// 官方文档: https://grafana.com/docs/alloy/latest/
//
// 数据流向:
// 应用程序 -> OTLP Receiver -> Batch Processor -> Exporters -> 后端存储
// - 日志 (Logs) -> Loki
// - 指标 (Metrics) -> Prometheus
// - 链路 (Traces) -> Tempo
// ============================================================================
// OTLP 接收器配置
// OpenTelemetry Protocol (OTLP) 是 OpenTelemetry 的标准数据传输协议
// 支持同时接收日志、指标和链路追踪数据
otelcol.receiver.otlp "default" {
// gRPC 协议配置
// gRPC 是高性能的 RPC 框架,适用于服务间通信
grpc {
endpoint = "0.0.0.0:4317"
// 0.0.0.0 表示监听所有网络接口
// 4317 是 OTLP gRPC 的标准端口
// 应用程序通过此端口发送遥测数据
}
// HTTP 协议配置
// HTTP 协议更通用,适用于无法使用 gRPC 的场景
http {
endpoint = "0.0.0.0:4318"
// 4318 是 OTLP HTTP 的标准端口
// 支持 JSON 和 Protobuf 格式的数据
}
// 输出配置
// 定义接收到的数据发送到哪些处理器
output {
logs = [otelcol.processor.batch.default.input]
metrics = [otelcol.processor.batch.default.input]
traces = [otelcol.processor.batch.default.input]
}
}
// 批处理器配置
// 将多个遥测数据项合并成批次,提高传输效率
otelcol.processor.batch "default" {
// 输出配置
// 定义处理后的数据发送到哪些导出器
output {
logs = [otelcol.exporter.loki.default.input]
metrics = [otelcol.exporter.prometheus.default.input]
traces = [otelcol.exporter.otlp.tempo.input]
}
}
// Loki 导出器配置
// 将日志数据发送到 Grafana Loki
otelcol.exporter.loki "default" {
forward_to = [loki.write.loki_server.receiver]
}
// Loki 写入组件
// 负责将日志数据推送到 Loki 服务器
loki.write "loki_server" {
endpoint {
url = "http://fba_loki:3100/loki/api/v1/push"
}
}
// Prometheus 导出器配置
// 将指标数据发送到 Prometheus
otelcol.exporter.prometheus "default" {
forward_to = [prometheus.remote_write.prom_server.receiver]
}
// Prometheus 远程写入组件
// 负责将指标数据推送到 Prometheus 服务器
prometheus.remote_write "prom_server" {
endpoint {
url = "http://fba_prometheus:9090/api/v1/write"
}
}
// Prometheus 自身指标抓取
// 监控 Prometheus 服务器本身的运行状态
prometheus.scrape "prometheus" {
targets = [{
__address__ = "fba_prometheus:9090",
}]
forward_to = [prometheus.remote_write.prom_server.receiver]
// 抓取的指标发送到远程写入组件
job_name = "fba_prometheus"
// 任务名称
// 将作为 job 标签添加到所有抓取的指标上
scrape_interval = "15s"
// 抓取间隔
}
// FastAPI 后端服务指标抓取
// 监控 FastAPI 应用的性能和业务指标
prometheus.scrape "fba_server" {
targets = [{
__address__ = "fba_server:8001",
}]
forward_to = [prometheus.remote_write.prom_server.receiver]
// 抓取的指标发送到远程写入组件
job_name = "fba_server"
// 任务名称
// 用于在 Prometheus 查询中区分不同服务
scrape_interval = "5s"
// 抓取间隔
scrape_timeout = "5s"
// 抓取超时时间
}
// Celery Exporter 指标抓取
// 监控 Celery 异步任务队列的运行状态
prometheus.scrape "fba_celery_exporter" {
targets = [{
__address__ = "fba_celery_exporter:9808",
}]
forward_to = [prometheus.remote_write.prom_server.receiver]
// 抓取的指标发送到远程写入组件
job_name = "fba_celery_exporter"
// 任务名称
// 用于标识 Celery 相关的指标
scrape_interval = "5s"
// 抓取间隔
scrape_timeout = "5s"
// 抓取超时时间
}
// Tempo 导出器配置
// 将链路追踪数据发送到 Grafana Tempo
otelcol.exporter.otlp "tempo" {
client {
endpoint = "fba_tempo:4317"
tls {
insecure = true
// 禁用 TLS 加密
// 在 Docker 内部网络中通信时可以禁用
// 生产环境建议启用 TLS
insecure_skip_verify = true
// 跳过 TLS 证书验证
// 仅在开发/测试环境使用
// 生产环境应配置正确的证书
}
}
}

View File

@@ -0,0 +1,36 @@
# ============================================================================
# Grafana 仪表盘 Provisioning 配置文件
# 官方文档: https://grafana.com/docs/grafana/latest/administration/provisioning/#dashboards
# 用于自动加载和管理仪表盘,无需手动导入
# ============================================================================
# API 版本号
# 当前仅支持版本 1
apiVersion: 1
# providers: 仪表盘提供者列表
# 定义 Grafana 从哪里加载仪表盘以及如何管理它们
providers:
- name: 'fba_server'
# 提供者名称,用于标识和日志记录
orgId: 1
# 组织 ID
# 指定仪表盘属于哪个组织
# 默认值: 1默认组织
type: 'file'
# 提供者类型
# 可选值:
# - file: 从本地文件系统加载仪表盘 JSON 文件
disableDeletion: true
# 禁止通过 UI 删除仪表盘
editable: false
# 是否允许通过 UI 编辑仪表盘
options:
path: '/etc/grafana/dashboards'
# 仪表盘 JSON 文件所在目录(容器内路径)
# Grafana 会自动扫描此目录下的所有 .json 文件

View File

@@ -0,0 +1,164 @@
# ============================================================================
# Grafana 数据源 Provisioning 配置文件
# 官方文档: https://grafana.com/docs/grafana/latest/administration/provisioning/#datasources
# 用于自动配置数据源,实现基础设施即代码
# ============================================================================
# API 版本号
# 当前仅支持版本 1
apiVersion: 1
# datasources: 数据源列表
# 定义 Grafana 连接的所有后端数据存储
datasources:
# ==========================================================================
# Loki 数据源配置
# Loki 是 Grafana 的日志聚合系统,类似于 Prometheus 但用于日志
# 官方文档: https://grafana.com/docs/loki/latest/
# ==========================================================================
- name: Loki
# 数据源显示名称,在 Grafana UI 中显示
uid: loki
# 数据源唯一标识符
# 用于在仪表盘和告警规则中引用此数据源
type: loki
# 数据源类型
# 必须与 Grafana 支持的数据源插件类型匹配
url: http://fba_loki:3100
# Loki 服务器地址
isDefault: false
# 是否设为默认数据源
jsonData:
# 数据源特定的 JSON 配置
derivedFields:
# 派生字段配置
# 用于从日志中提取字段并创建链接到其他数据源
# 这是实现日志到链路追踪关联的关键配置
- datasourceUid: tempo
# 目标数据源的 UID
# 点击链接时将跳转到此数据源
matcherRegex: '"traceid":"([a-f0-9]{32})"'
# 正则表达式,用于从日志内容中提取 Trace ID
matcherType: regex
# 匹配器类型
# 可选值: regex正则表达式
name: TraceID
# 派生字段的名称
# 将显示在日志详情中
url: $${__value.raw}
# 链接 URL 模板
# $${__value.raw} 表示提取的原始值
urlDisplayLabel: 查看 Trace
# 链接显示的文本标签
# ==========================================================================
# Prometheus 数据源配置
# Prometheus 是云原生监控系统,用于收集和存储时序指标数据
# 官方文档: https://prometheus.io/docs/
# ==========================================================================
- name: Prometheus
# 数据源显示名称
uid: prometheus
# 数据源唯一标识符
type: prometheus
# 数据源类型
url: http://fba_prometheus:9090
# Prometheus 服务器地址
isDefault: true
# 设为默认数据源
jsonData:
httpMethod: POST
# 查询使用的 HTTP 方法
exemplarTraceIdDestinations:
# Exemplar范例配置
# Exemplar 是指标数据点关联的 Trace ID
# 用于从指标跳转到对应的链路追踪
- name: TraceID
# Exemplar 中 Trace ID 的字段名称
datasourceUid: tempo
# 目标 Tempo 数据源的 UID
# 点击 Exemplar 时将跳转到此数据源查看 Trace
# ==========================================================================
# Tempo 数据源配置
# Tempo 是 Grafana 的分布式链路追踪后端
# 官方文档: https://grafana.com/docs/tempo/latest/
# ==========================================================================
- name: Tempo
# 数据源显示名称
uid: tempo
# 数据源唯一标识符
type: tempo
# 数据源类型
url: http://fba_tempo:3200
# Tempo 服务器地址
jsonData:
nodeGraph:
enabled: true
# 启用节点图功能
# 可视化展示服务之间的调用关系图
tracesToLogsV2:
# Trace 到日志的关联配置V2 版本)
# 允许从 Trace 详情页面跳转到相关日志
datasourceUid: loki
# 日志数据源的 UID
filterByTraceID: true
# 是否按 Trace ID 过滤日志
spanStartTimeShift: "-1m"
# Span 开始时间偏移
# 用于捕获 Span 开始前的相关日志
spanEndTimeShift: "1m"
# Span 结束时间偏移
# 用于捕获 Span 结束后的相关日志
customQuery: true
# 启用自定义查询
# 允许使用下面的 query 字段自定义日志查询语句
query: '{service_name="fba_server"} | json | traceid="${__span.traceId}"'
# 自定义 LogQL 查询语句
search:
hide: false
# 是否隐藏搜索功能
serviceMap:
datasourceUid: prometheus
# 服务地图数据源
# 使用 Prometheus 中的指标数据生成服务依赖图
# 需要 Tempo 的 metrics_generator 功能配合
lokiSearch:
datasourceUid: loki
# Loki 搜索数据源
# 允许在 Tempo 中使用 Loki 进行日志搜索
# 实现基于日志内容查找 Trace 的功能

View File

@@ -0,0 +1,40 @@
# ============================================================================
# Grafana 主配置文件
# 官方文档: https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/
# ============================================================================
# [server] 服务器配置
# 用于配置 Grafana HTTP 服务器的基本设置
[server]
# 协议类型
protocol = http
# HTTP 服务监听端口
http_port = 3000
# [security] 安全配置
# 用于配置 Grafana 安全相关的默认设置
[security]
# 默认 Grafana 管理员用户名
admin_user = admin
# 默认 Grafana 管理员密码
admin_password = 123456
# 如果您将 Grafana 托管在 HTTPS
;cookie_secure = true
# [users] 用户配置
# 用于配置用户相关的默认设置
[users]
# 默认 UI 主题
default_theme=system
# 默认界面语言
default_language = zh-Hans
# [dashboards] 仪表盘配置
# 用于配置仪表盘相关的默认设置
[dashboards]
# 默认首页仪表盘路径
default_home_dashboard_path = /etc/grafana/dashboards/fba_server.json

View File

@@ -0,0 +1,13 @@
# ============================================================================
# Prometheus 配置文件
# Prometheus 是云原生监控和告警系统,专注于时序指标数据
# 官方文档: https://prometheus.io/docs/prometheus/latest/configuration/configuration/
# ============================================================================
# global: 全局配置
global:
scrape_interval: 15s
# 指标抓取间隔
evaluation_interval: 15s
# 规则评估间隔

View File

@@ -0,0 +1,127 @@
# ============================================================================
# Tempo 配置文件
# Tempo 是 Grafana 的高性能、低成本分布式链路追踪后端
# 官方文档: https://grafana.com/docs/tempo/latest/configuration/
# ============================================================================
# server: HTTP 服务器配置
server:
http_listen_port: 3200
# HTTP API 监听端口
# 用于查询 Trace 数据和健康检查
# distributor: 分发器配置
distributor:
receivers:
# 接收器配置
otlp:
# OpenTelemetry Protocol (OTLP) 接收器
# OTLP 是 OpenTelemetry 的原生协议,推荐使用
protocols:
grpc:
endpoint: "0.0.0.0:4317"
# gRPC 协议端点
http:
endpoint: "0.0.0.0:4318"
# HTTP 协议端点
# storage: 存储配置
storage:
trace:
backend: local
# 存储后端类型
# 生产环境建议使用对象存储
wal:
path: /tmp/tempo/wal
# Write-Ahead Log (WAL) 目录
# WAL 用于在数据写入存储前的临时缓存
# 确保数据不会因意外重启而丢失
# 注意: 生产环境应使用持久化存储路径
local:
path: /tmp/tempo/blocks
# 本地存储的数据块目录
# 存储压缩后的 Trace 数据块
# 仅在 backend: local 时使用
# metrics_generator: 指标生成器配置
# 从 Trace 数据自动生成 Prometheus 指标
# 这是实现 Trace 到 Metrics 关联的关键功能
metrics_generator:
registry:
external_labels:
source: tempo
# 外部标签
# 添加到所有生成的指标上
storage:
path: /tmp/tempo/generator/wal
# 指标生成器的 WAL 目录
# 用于临时存储待发送的指标数据
remote_write:
# 远程写入配置
- url: http://fba_prometheus:9090/api/v1/write
# Prometheus 远程写入 API 地址
# 需要 Prometheus 启用 remote-write-receiver 功能
send_exemplars: true
# 发送 Exemplar 数据
# Exemplar 将指标数据点与 Trace ID 关联
# 实现从指标图表点击跳转到对应 Trace
traces_storage:
path: /tmp/tempo/generator/traces
# Trace 数据临时存储路径
# 用于指标生成器处理 Trace 数据
processor:
# 处理器配置
# 定义如何从 Trace 生成指标
span_metrics:
# Span 指标处理器
dimensions:
# 指标维度(标签)
# 这些属性将作为 Prometheus 指标的标签
- service.name
- http.method
- http.target
- http.status_code
service_graphs:
# 服务图处理器
# 生成服务间调用关系的指标
# 用于 Grafana 中的服务地图可视化
dimensions:
- service.name
local_blocks:
# 本地块处理器
# 处理本地存储的 Trace 数据块
flush_to_storage: true
# 是否将处理后的数据刷新到存储
# overrides: 覆盖配置
overrides:
defaults:
# 默认配置
# 适用于所有租户(单租户模式下为全局配置)
metrics_generator:
processors:
# 启用的指标处理器列表
# 只有在此列表中的处理器才会运行
- span-metrics
- service-graphs
- local-blocks

View File

@@ -19,6 +19,8 @@ volumes:
name: fba_static_upload
fba_rabbitmq:
name: fba_rabbitmq
fba_prometheus_data:
name: fba_prometheus_data
services:
fba_server:
@@ -30,6 +32,8 @@ services:
- "8001:8001"
container_name: fba_server
restart: always
environment:
- TZ=Asia/Shanghai
# 如果你是 mysql 用户,应将 fba_postgres 修改为 fba_mysql
depends_on:
- fba_postgres
@@ -176,6 +180,8 @@ services:
# 如果你需要分布式部署 Worker则必须移除此 container_name 配置
container_name: fba_celery_worker
restart: always
environment:
- TZ=Asia/Shanghai
depends_on:
- fba_rabbitmq
volumes:
@@ -199,6 +205,8 @@ services:
image: fba_celery_beat:latest
container_name: fba_celery_beat
restart: always
environment:
- TZ=Asia/Shanghai
depends_on:
- fba_rabbitmq
- fba_celery_worker
@@ -225,6 +233,8 @@ services:
- "8555:8555"
container_name: fba_celery_flower
restart: always
environment:
- TZ=Asia/Shanghai
depends_on:
- fba_rabbitmq
- fba_celery_worker
@@ -239,3 +249,100 @@ services:
wait-for-it -s fba_rabbitmq:5672 -t 300
supervisord -c /etc/supervisor/supervisord.conf
supervisorctl restart
fba_celery_exporter:
image: danihodovic/celery-exporter
restart: always
ports:
- "9808:9808"
container_name: fba_celery_exporter
environment:
- CE_BROKER_URL=amqp://guest:guest@fba_rabbitmq:5672//
depends_on:
- fba_rabbitmq
networks:
- fba_network
fba_loki:
image: grafana/loki
restart: always
ports:
- "3100:3100"
container_name: fba_loki
networks:
- fba_network
command: -config.file=/etc/loki/local-config.yaml
fba_prometheus:
image: prom/prometheus
restart: always
ports:
- "9090:9090"
container_name: fba_prometheus
depends_on:
- fba_loki
volumes:
- ./deploy/backend/grafana/fba_prometheus.yml:/workspace/fba_prometheus.yml
- fba_prometheus_data:/prometheus
networks:
- fba_network
command:
- --web.enable-remote-write-receiver
- --enable-feature=exemplar-storage
- --config.file=/workspace/fba_prometheus.yml
fba_alloy:
image: grafana/alloy
restart: always
ports:
- "4317:4317"
- "4318:4318"
- "12345:12345"
container_name: fba_alloy
depends_on:
- fba_loki
volumes:
- ./deploy/backend/grafana/fba_config.alloy:/etc/alloy/fba_config.alloy
networks:
- fba_network
command:
- run
- /etc/alloy/fba_config.alloy
- --server.http.listen-addr=0.0.0.0:12345
fba_tempo:
image: grafana/tempo:latest
restart: always
ports:
- "3200:3200"
expose:
- 4317
- 4318
container_name: fba_tempo
depends_on:
- fba_loki
volumes:
- ./deploy/backend/grafana/fba_tempo.yml:/etc/tempo/fba_tempo.yml
networks:
- fba_network
command:
- -config.file=/etc/tempo/fba_tempo.yml
- -auth.enabled=false
fba_grafana:
image: grafana/grafana
restart: always
ports:
- "3000:3000"
container_name: fba_grafana
depends_on:
- fba_loki
- fba_prometheus
volumes:
- ./deploy/backend/grafana/fba_grafana.ini:/etc/grafana/grafana.ini
- ./deploy/backend/grafana/dashboards/fba_celery.json:/etc/grafana/dashboards/fba_celery.json
- ./deploy/backend/grafana/dashboards/fba_server.json:/etc/grafana/dashboards/fba_server.json
- ./deploy/backend/grafana/fba_dashboards.yml:/etc/grafana/provisioning/dashboards/fba_dashboards.yml
- ./deploy/backend/grafana/fba_datasource.yml:/etc/grafana/provisioning/datasources/fba_datasource.yml
networks:
- fba_network

View File

@@ -36,6 +36,12 @@ dependencies = [
"jinja2>=3.1.6",
"loguru>=0.7.3",
"msgspec>=0.20.0",
"opentelemetry-exporter-otlp-proto-grpc>=1.39.0",
"opentelemetry-instrumentation-fastapi>=0.60b0",
"opentelemetry-instrumentation-logging>=0.60b0",
"opentelemetry-instrumentation-sqlalchemy>=0.60b0",
"opentelemetry-sdk>=1.39.0",
"prometheus-client>=0.23.1",
"psutil>=7.1.3",
# https://github.com/fastapi-practices/fastapi_best_architecture/issues/887
"psycopg[binary]==3.2.10",

View File

@@ -15,7 +15,9 @@ anyio==4.12.0
# starlette
# watchfiles
asgiref==3.11.0
# via fastapi-best-architecture
# via
# fastapi-best-architecture
# opentelemetry-instrumentation-asgi
async-timeout==5.0.1 ; python_full_version < '3.11.3'
# via
# asyncpg
@@ -101,12 +103,16 @@ flower==2.0.1
# via fastapi-best-architecture
gevent==25.9.1
# via fastapi-best-architecture
googleapis-common-protos==1.72.0
# via opentelemetry-exporter-otlp-proto-grpc
granian==2.6.0
# via fastapi-best-architecture
greenlet==3.2.4
# via
# gevent
# sqlalchemy
grpcio==1.76.0
# via opentelemetry-exporter-otlp-proto-grpc
h11==0.16.0
# via
# httpcore
@@ -127,6 +133,8 @@ idna==3.11
# anyio
# email-validator
# httpx
importlib-metadata==8.7.0
# via opentelemetry-api
iniconfig==2.3.0
# via pytest
ip2loc==1.0.0
@@ -153,9 +161,58 @@ mdurl==0.1.2
# via markdown-it-py
msgspec==0.20.0
# via fastapi-best-architecture
opentelemetry-api==1.39.0
# via
# opentelemetry-exporter-otlp-proto-grpc
# opentelemetry-instrumentation
# opentelemetry-instrumentation-asgi
# opentelemetry-instrumentation-fastapi
# opentelemetry-instrumentation-logging
# opentelemetry-instrumentation-sqlalchemy
# opentelemetry-sdk
# opentelemetry-semantic-conventions
opentelemetry-exporter-otlp-proto-common==1.39.0
# via opentelemetry-exporter-otlp-proto-grpc
opentelemetry-exporter-otlp-proto-grpc==1.39.0
# via fastapi-best-architecture
opentelemetry-instrumentation==0.60b0
# via
# opentelemetry-instrumentation-asgi
# opentelemetry-instrumentation-fastapi
# opentelemetry-instrumentation-logging
# opentelemetry-instrumentation-sqlalchemy
opentelemetry-instrumentation-asgi==0.60b0
# via opentelemetry-instrumentation-fastapi
opentelemetry-instrumentation-fastapi==0.60b0
# via fastapi-best-architecture
opentelemetry-instrumentation-logging==0.60b0
# via fastapi-best-architecture
opentelemetry-instrumentation-sqlalchemy==0.60b0
# via fastapi-best-architecture
opentelemetry-proto==1.39.0
# via
# opentelemetry-exporter-otlp-proto-common
# opentelemetry-exporter-otlp-proto-grpc
opentelemetry-sdk==1.39.0
# via
# fastapi-best-architecture
# opentelemetry-exporter-otlp-proto-grpc
opentelemetry-semantic-conventions==0.60b0
# via
# opentelemetry-instrumentation
# opentelemetry-instrumentation-asgi
# opentelemetry-instrumentation-fastapi
# opentelemetry-instrumentation-sqlalchemy
# opentelemetry-sdk
opentelemetry-util-http==0.60b0
# via
# opentelemetry-instrumentation-asgi
# opentelemetry-instrumentation-fastapi
packaging==25.0
# via
# kombu
# opentelemetry-instrumentation
# opentelemetry-instrumentation-sqlalchemy
# pytest
pillow==12.0.0
# via fast-captcha
@@ -163,9 +220,15 @@ pluggy==1.6.0
# via pytest
prek==0.2.19
prometheus-client==0.23.1
# via flower
# via
# fastapi-best-architecture
# flower
prompt-toolkit==3.0.52
# via click-repl
protobuf==6.33.2
# via
# googleapis-common-protos
# opentelemetry-proto
psutil==7.1.3
# via fastapi-best-architecture
psycopg==3.2.10
@@ -280,6 +343,11 @@ typing-extensions==4.15.0
# exceptiongroup
# fastapi
# fastapi-pagination
# grpcio
# opentelemetry-api
# opentelemetry-exporter-otlp-proto-grpc
# opentelemetry-sdk
# opentelemetry-semantic-conventions
# psycopg
# pydantic
# pydantic-core
@@ -328,8 +396,14 @@ websockets==15.0.1
# via uvicorn
win32-setctime==1.2.0 ; sys_platform == 'win32'
# via loguru
wrapt==1.17.3
# via
# opentelemetry-instrumentation
# opentelemetry-instrumentation-sqlalchemy
wsproto==1.3.2
# via simple-websocket
zipp==3.23.0
# via importlib-metadata
zope-event==6.1
# via gevent
zope-interface==8.1.1

357
uv.lock generated
View File

@@ -704,6 +704,12 @@ dependencies = [
{ name = "jinja2" },
{ name = "loguru" },
{ name = "msgspec" },
{ name = "opentelemetry-exporter-otlp-proto-grpc" },
{ name = "opentelemetry-instrumentation-fastapi" },
{ name = "opentelemetry-instrumentation-logging" },
{ name = "opentelemetry-instrumentation-sqlalchemy" },
{ name = "opentelemetry-sdk" },
{ name = "prometheus-client" },
{ name = "psutil" },
{ name = "psycopg", extra = ["binary"] },
{ name = "pwdlib" },
@@ -758,6 +764,12 @@ requires-dist = [
{ name = "jinja2", specifier = ">=3.1.6" },
{ name = "loguru", specifier = ">=0.7.3" },
{ name = "msgspec", specifier = ">=0.20.0" },
{ name = "opentelemetry-exporter-otlp-proto-grpc", specifier = ">=1.39.0" },
{ name = "opentelemetry-instrumentation-fastapi", specifier = ">=0.60b0" },
{ name = "opentelemetry-instrumentation-logging", specifier = ">=0.60b0" },
{ name = "opentelemetry-instrumentation-sqlalchemy", specifier = ">=0.60b0" },
{ name = "opentelemetry-sdk", specifier = ">=1.39.0" },
{ name = "prometheus-client", specifier = ">=0.23.1" },
{ name = "psutil", specifier = ">=7.1.3" },
{ name = "psycopg", extras = ["binary"], specifier = "==3.2.10" },
{ name = "pwdlib", specifier = ">=0.3.0" },
@@ -901,6 +913,18 @@ wheels = [
{ url = "https://mirrors.aliyun.com/pypi/packages/c2/69/a7c4ba2ffbc7c7dbf6d8b4f5d0f0a421f7815d229f4909854266c445a3d4/gevent-25.9.1-cp314-cp314-win_amd64.whl", hash = "sha256:bb63c0d6cb9950cc94036a4995b9cc4667b8915366613449236970f4394f94d7" },
]
[[package]]
name = "googleapis-common-protos"
version = "1.72.0"
source = { registry = "https://mirrors.aliyun.com/pypi/simple" }
dependencies = [
{ name = "protobuf" },
]
sdist = { url = "https://mirrors.aliyun.com/pypi/packages/e5/7b/adfd75544c415c487b33061fe7ae526165241c1ea133f9a9125a56b39fd8/googleapis_common_protos-1.72.0.tar.gz", hash = "sha256:e55a601c1b32b52d7a3e65f43563e2aa61bcd737998ee672ac9b951cd49319f5" }
wheels = [
{ url = "https://mirrors.aliyun.com/pypi/packages/c4/ab/09169d5a4612a5f92490806649ac8d41e3ec9129c636754575b3553f4ea4/googleapis_common_protos-1.72.0-py3-none-any.whl", hash = "sha256:4299c5a82d5ae1a9702ada957347726b167f9f8d1fc352477702a1e851ff4038" },
]
[[package]]
name = "granian"
version = "2.6.0"
@@ -1051,6 +1075,67 @@ wheels = [
{ url = "https://mirrors.aliyun.com/pypi/packages/e3/a5/6ddab2b4c112be95601c13428db1d8b6608a8b6039816f2ba09c346c08fc/greenlet-3.2.4-cp314-cp314-win_amd64.whl", hash = "sha256:e37ab26028f12dbb0ff65f29a8d3d44a765c61e729647bf2ddfbbed621726f01" },
]
[[package]]
name = "grpcio"
version = "1.76.0"
source = { registry = "https://mirrors.aliyun.com/pypi/simple" }
dependencies = [
{ name = "typing-extensions" },
]
sdist = { url = "https://mirrors.aliyun.com/pypi/packages/b6/e0/318c1ce3ae5a17894d5791e87aea147587c9e702f24122cc7a5c8bbaeeb1/grpcio-1.76.0.tar.gz", hash = "sha256:7be78388d6da1a25c0d5ec506523db58b18be22d9c37d8d3a32c08be4987bd73" }
wheels = [
{ url = "https://mirrors.aliyun.com/pypi/packages/88/17/ff4795dc9a34b6aee6ec379f1b66438a3789cd1315aac0cbab60d92f74b3/grpcio-1.76.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:65a20de41e85648e00305c1bb09a3598f840422e522277641145a32d42dcefcc" },
{ url = "https://mirrors.aliyun.com/pypi/packages/4e/ff/35f9b96e3fa2f12e1dcd58a4513a2e2294a001d64dec81677361b7040c9a/grpcio-1.76.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:40ad3afe81676fd9ec6d9d406eda00933f218038433980aa19d401490e46ecde" },
{ url = "https://mirrors.aliyun.com/pypi/packages/3e/1c/8374990f9545e99462caacea5413ed783014b3b66ace49e35c533f07507b/grpcio-1.76.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:035d90bc79eaa4bed83f524331d55e35820725c9fbb00ffa1904d5550ed7ede3" },
{ url = "https://mirrors.aliyun.com/pypi/packages/1e/77/36fd7d7c75a6c12542c90a6d647a27935a1ecaad03e0ffdb7c42db6b04d2/grpcio-1.76.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:4215d3a102bd95e2e11b5395c78562967959824156af11fa93d18fdd18050990" },
{ url = "https://mirrors.aliyun.com/pypi/packages/38/f7/e3cdb252492278e004722306c5a8935eae91e64ea11f0af3437a7de2e2b7/grpcio-1.76.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:49ce47231818806067aea3324d4bf13825b658ad662d3b25fada0bdad9b8a6af" },
{ url = "https://mirrors.aliyun.com/pypi/packages/7e/20/340db7af162ccd20a0893b5f3c4a5d676af7b71105517e62279b5b61d95a/grpcio-1.76.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8cc3309d8e08fd79089e13ed4819d0af72aa935dd8f435a195fd152796752ff2" },
{ url = "https://mirrors.aliyun.com/pypi/packages/10/f0/b2160addc1487bd8fa4810857a27132fb4ce35c1b330c2f3ac45d697b106/grpcio-1.76.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:971fd5a1d6e62e00d945423a567e42eb1fa678ba89072832185ca836a94daaa6" },
{ url = "https://mirrors.aliyun.com/pypi/packages/2c/2c/ac6f98aa113c6ef111b3f347854e99ebb7fb9d8f7bb3af1491d438f62af4/grpcio-1.76.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9d9adda641db7207e800a7f089068f6f645959f2df27e870ee81d44701dd9db3" },
{ url = "https://mirrors.aliyun.com/pypi/packages/90/84/7852f7e087285e3ac17a2703bc4129fafee52d77c6c82af97d905566857e/grpcio-1.76.0-cp310-cp310-win32.whl", hash = "sha256:063065249d9e7e0782d03d2bca50787f53bd0fb89a67de9a7b521c4a01f1989b" },
{ url = "https://mirrors.aliyun.com/pypi/packages/10/30/d3d2adcbb6dd3ff59d6ac3df6ef830e02b437fb5c90990429fd180e52f30/grpcio-1.76.0-cp310-cp310-win_amd64.whl", hash = "sha256:a6ae758eb08088d36812dd5d9af7a9859c05b1e0f714470ea243694b49278e7b" },
{ url = "https://mirrors.aliyun.com/pypi/packages/a0/00/8163a1beeb6971f66b4bbe6ac9457b97948beba8dd2fc8e1281dce7f79ec/grpcio-1.76.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:2e1743fbd7f5fa713a1b0a8ac8ebabf0ec980b5d8809ec358d488e273b9cf02a" },
{ url = "https://mirrors.aliyun.com/pypi/packages/10/c1/934202f5cf335e6d852530ce14ddb0fef21be612ba9ecbbcbd4d748ca32d/grpcio-1.76.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:a8c2cf1209497cf659a667d7dea88985e834c24b7c3b605e6254cbb5076d985c" },
{ url = "https://mirrors.aliyun.com/pypi/packages/11/0b/8dec16b1863d74af6eb3543928600ec2195af49ca58b16334972f6775663/grpcio-1.76.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:08caea849a9d3c71a542827d6df9d5a69067b0a1efbea8a855633ff5d9571465" },
{ url = "https://mirrors.aliyun.com/pypi/packages/d7/64/7b9e6e7ab910bea9d46f2c090380bab274a0b91fb0a2fe9b0cd399fffa12/grpcio-1.76.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:f0e34c2079d47ae9f6188211db9e777c619a21d4faba6977774e8fa43b085e48" },
{ url = "https://mirrors.aliyun.com/pypi/packages/68/86/093c46e9546073cefa789bd76d44c5cb2abc824ca62af0c18be590ff13ba/grpcio-1.76.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8843114c0cfce61b40ad48df65abcfc00d4dba82eae8718fab5352390848c5da" },
{ url = "https://mirrors.aliyun.com/pypi/packages/f7/b6/5709a3a68500a9c03da6fb71740dcdd5ef245e39266461a03f31a57036d8/grpcio-1.76.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8eddfb4d203a237da6f3cc8a540dad0517d274b5a1e9e636fd8d2c79b5c1d397" },
{ url = "https://mirrors.aliyun.com/pypi/packages/91/d3/4b1f2bf16ed52ce0b508161df3a2d186e4935379a159a834cb4a7d687429/grpcio-1.76.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:32483fe2aab2c3794101c2a159070584e5db11d0aa091b2c0ea9c4fc43d0d749" },
{ url = "https://mirrors.aliyun.com/pypi/packages/5c/61/d9043f95f5f4cf085ac5dd6137b469d41befb04bd80280952ffa2a4c3f12/grpcio-1.76.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:dcfe41187da8992c5f40aa8c5ec086fa3672834d2be57a32384c08d5a05b4c00" },
{ url = "https://mirrors.aliyun.com/pypi/packages/36/95/fd9a5152ca02d8881e4dd419cdd790e11805979f499a2e5b96488b85cf27/grpcio-1.76.0-cp311-cp311-win32.whl", hash = "sha256:2107b0c024d1b35f4083f11245c0e23846ae64d02f40b2b226684840260ed054" },
{ url = "https://mirrors.aliyun.com/pypi/packages/60/9c/5c359c8d4c9176cfa3c61ecd4efe5affe1f38d9bae81e81ac7186b4c9cc8/grpcio-1.76.0-cp311-cp311-win_amd64.whl", hash = "sha256:522175aba7af9113c48ec10cc471b9b9bd4f6ceb36aeb4544a8e2c80ed9d252d" },
{ url = "https://mirrors.aliyun.com/pypi/packages/bf/05/8e29121994b8d959ffa0afd28996d452f291b48cfc0875619de0bde2c50c/grpcio-1.76.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:81fd9652b37b36f16138611c7e884eb82e0cec137c40d3ef7c3f9b3ed00f6ed8" },
{ url = "https://mirrors.aliyun.com/pypi/packages/d9/75/11d0e66b3cdf998c996489581bdad8900db79ebd83513e45c19548f1cba4/grpcio-1.76.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:04bbe1bfe3a68bbfd4e52402ab7d4eb59d72d02647ae2042204326cf4bbad280" },
{ url = "https://mirrors.aliyun.com/pypi/packages/28/50/2f0aa0498bc188048f5d9504dcc5c2c24f2eb1a9337cd0fa09a61a2e75f0/grpcio-1.76.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d388087771c837cdb6515539f43b9d4bf0b0f23593a24054ac16f7a960be16f4" },
{ url = "https://mirrors.aliyun.com/pypi/packages/66/e5/bbf0bb97d29ede1d59d6588af40018cfc345b17ce979b7b45424628dc8bb/grpcio-1.76.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:9f8f757bebaaea112c00dba718fc0d3260052ce714e25804a03f93f5d1c6cc11" },
{ url = "https://mirrors.aliyun.com/pypi/packages/f5/86/f6ec2164f743d9609691115ae8ece098c76b894ebe4f7c94a655c6b03e98/grpcio-1.76.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:980a846182ce88c4f2f7e2c22c56aefd515daeb36149d1c897f83cf57999e0b6" },
{ url = "https://mirrors.aliyun.com/pypi/packages/60/bc/8d9d0d8505feccfdf38a766d262c71e73639c165b311c9457208b56d92ae/grpcio-1.76.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f92f88e6c033db65a5ae3d97905c8fea9c725b63e28d5a75cb73b49bda5024d8" },
{ url = "https://mirrors.aliyun.com/pypi/packages/67/e6/5d6c2fc10b95edf6df9b8f19cf10a34263b7fd48493936fffd5085521292/grpcio-1.76.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4baf3cbe2f0be3289eb68ac8ae771156971848bb8aaff60bad42005539431980" },
{ url = "https://mirrors.aliyun.com/pypi/packages/3f/c8/dce8ff21c86abe025efe304d9e31fdb0deaaa3b502b6a78141080f206da0/grpcio-1.76.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:615ba64c208aaceb5ec83bfdce7728b80bfeb8be97562944836a7a0a9647d882" },
{ url = "https://mirrors.aliyun.com/pypi/packages/e0/42/ad28191ebf983a5d0ecef90bab66baa5a6b18f2bfdef9d0a63b1973d9f75/grpcio-1.76.0-cp312-cp312-win32.whl", hash = "sha256:45d59a649a82df5718fd9527ce775fd66d1af35e6d31abdcdc906a49c6822958" },
{ url = "https://mirrors.aliyun.com/pypi/packages/9e/00/7bd478cbb851c04a48baccaa49b75abaa8e4122f7d86da797500cccdd771/grpcio-1.76.0-cp312-cp312-win_amd64.whl", hash = "sha256:c088e7a90b6017307f423efbb9d1ba97a22aa2170876223f9709e9d1de0b5347" },
{ url = "https://mirrors.aliyun.com/pypi/packages/fc/ed/71467ab770effc9e8cef5f2e7388beb2be26ed642d567697bb103a790c72/grpcio-1.76.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:26ef06c73eb53267c2b319f43e6634c7556ea37672029241a056629af27c10e2" },
{ url = "https://mirrors.aliyun.com/pypi/packages/2c/85/c6ed56f9817fab03fa8a111ca91469941fb514e3e3ce6d793cb8f1e1347b/grpcio-1.76.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:45e0111e73f43f735d70786557dc38141185072d7ff8dc1829d6a77ac1471468" },
{ url = "https://mirrors.aliyun.com/pypi/packages/ac/31/2b8a235ab40c39cbc141ef647f8a6eb7b0028f023015a4842933bc0d6831/grpcio-1.76.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:83d57312a58dcfe2a3a0f9d1389b299438909a02db60e2f2ea2ae2d8034909d3" },
{ url = "https://mirrors.aliyun.com/pypi/packages/bd/64/9784eab483358e08847498ee56faf8ff6ea8e0a4592568d9f68edc97e9e9/grpcio-1.76.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:3e2a27c89eb9ac3d81ec8835e12414d73536c6e620355d65102503064a4ed6eb" },
{ url = "https://mirrors.aliyun.com/pypi/packages/2b/94/8c12319a6369434e7a184b987e8e9f3b49a114c489b8315f029e24de4837/grpcio-1.76.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:61f69297cba3950a524f61c7c8ee12e55c486cb5f7db47ff9dcee33da6f0d3ae" },
{ url = "https://mirrors.aliyun.com/pypi/packages/15/0f/f12c32b03f731f4a6242f771f63039df182c8b8e2cf8075b245b409259d4/grpcio-1.76.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6a15c17af8839b6801d554263c546c69c4d7718ad4321e3166175b37eaacca77" },
{ url = "https://mirrors.aliyun.com/pypi/packages/ff/2d/3ec9ce0c2b1d92dd59d1c3264aaec9f0f7c817d6e8ac683b97198a36ed5a/grpcio-1.76.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:25a18e9810fbc7e7f03ec2516addc116a957f8cbb8cbc95ccc80faa072743d03" },
{ url = "https://mirrors.aliyun.com/pypi/packages/1a/74/fd3317be5672f4856bcdd1a9e7b5e17554692d3db9a3b273879dc02d657d/grpcio-1.76.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:931091142fd8cc14edccc0845a79248bc155425eee9a98b2db2ea4f00a235a42" },
{ url = "https://mirrors.aliyun.com/pypi/packages/45/bb/ca038cf420f405971f19821c8c15bcbc875505f6ffadafe9ffd77871dc4c/grpcio-1.76.0-cp313-cp313-win32.whl", hash = "sha256:5e8571632780e08526f118f74170ad8d50fb0a48c23a746bef2a6ebade3abd6f" },
{ url = "https://mirrors.aliyun.com/pypi/packages/41/80/84087dc56437ced7cdd4b13d7875e7439a52a261e3ab4e06488ba6173b0a/grpcio-1.76.0-cp313-cp313-win_amd64.whl", hash = "sha256:f9f7bd5faab55f47231ad8dba7787866b69f5e93bc306e3915606779bbfb4ba8" },
{ url = "https://mirrors.aliyun.com/pypi/packages/b4/46/39adac80de49d678e6e073b70204091e76631e03e94928b9ea4ecf0f6e0e/grpcio-1.76.0-cp314-cp314-linux_armv7l.whl", hash = "sha256:ff8a59ea85a1f2191a0ffcc61298c571bc566332f82e5f5be1b83c9d8e668a62" },
{ url = "https://mirrors.aliyun.com/pypi/packages/9c/f5/a4531f7fb8b4e2a60b94e39d5d924469b7a6988176b3422487be61fe2998/grpcio-1.76.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:06c3d6b076e7b593905d04fdba6a0525711b3466f43b3400266f04ff735de0cd" },
{ url = "https://mirrors.aliyun.com/pypi/packages/4b/1c/de55d868ed7a8bd6acc6b1d6ddc4aa36d07a9f31d33c912c804adb1b971b/grpcio-1.76.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fd5ef5932f6475c436c4a55e4336ebbe47bd3272be04964a03d316bbf4afbcbc" },
{ url = "https://mirrors.aliyun.com/pypi/packages/59/64/99e44c02b5adb0ad13ab3adc89cb33cb54bfa90c74770f2607eea629b86f/grpcio-1.76.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:b331680e46239e090f5b3cead313cc772f6caa7d0fc8de349337563125361a4a" },
{ url = "https://mirrors.aliyun.com/pypi/packages/43/28/40a5be3f9a86949b83e7d6a2ad6011d993cbe9b6bd27bea881f61c7788b6/grpcio-1.76.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2229ae655ec4e8999599469559e97630185fdd53ae1e8997d147b7c9b2b72cba" },
{ url = "https://mirrors.aliyun.com/pypi/packages/4b/a9/1be18e6055b64467440208a8559afac243c66a8b904213af6f392dc2212f/grpcio-1.76.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:490fa6d203992c47c7b9e4a9d39003a0c2bcc1c9aa3c058730884bbbb0ee9f09" },
{ url = "https://mirrors.aliyun.com/pypi/packages/0f/55/dba05d3fcc151ce6e81327541d2cc8394f442f6b350fead67401661bf041/grpcio-1.76.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:479496325ce554792dba6548fae3df31a72cef7bad71ca2e12b0e58f9b336bfc" },
{ url = "https://mirrors.aliyun.com/pypi/packages/4a/45/122df922d05655f63930cf42c9e3f72ba20aadb26c100ee105cad4ce4257/grpcio-1.76.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:1c9b93f79f48b03ada57ea24725d83a30284a012ec27eab2cf7e50a550cbbbcc" },
{ url = "https://mirrors.aliyun.com/pypi/packages/4a/6e/0b899b7f6b66e5af39e377055fb4a6675c9ee28431df5708139df2e93233/grpcio-1.76.0-cp314-cp314-win32.whl", hash = "sha256:747fa73efa9b8b1488a95d0ba1039c8e2dca0f741612d80415b1e1c560febf4e" },
{ url = "https://mirrors.aliyun.com/pypi/packages/19/41/0b430b01a2eb38ee887f88c1f07644a1df8e289353b78e82b37ef988fb64/grpcio-1.76.0-cp314-cp314-win_amd64.whl", hash = "sha256:922fa70ba549fce362d2e2871ab542082d66e2aaf0c19480ea453905b01f384e" },
]
[[package]]
name = "h11"
version = "0.16.0"
@@ -1235,6 +1320,18 @@ wheels = [
{ url = "https://mirrors.aliyun.com/pypi/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea" },
]
[[package]]
name = "importlib-metadata"
version = "8.7.0"
source = { registry = "https://mirrors.aliyun.com/pypi/simple" }
dependencies = [
{ name = "zipp" },
]
sdist = { url = "https://mirrors.aliyun.com/pypi/packages/76/66/650a33bd90f786193e4de4b3ad86ea60b53c89b669a5c7be931fac31cdb0/importlib_metadata-8.7.0.tar.gz", hash = "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000" }
wheels = [
{ url = "https://mirrors.aliyun.com/pypi/packages/20/b0/36bd937216ec521246249be3bf9855081de4c5e06a0c9b4219dbeda50373/importlib_metadata-8.7.0-py3-none-any.whl", hash = "sha256:e5dd1551894c77868a30651cef00984d50e1002d06942a7101d34870c5f02afd" },
]
[[package]]
name = "iniconfig"
version = "2.3.0"
@@ -1614,6 +1711,173 @@ wheels = [
{ url = "https://mirrors.aliyun.com/pypi/packages/b7/da/7d22601b625e241d4f23ef1ebff8acfc60da633c9e7e7922e24d10f592b3/multidict-6.7.0-py3-none-any.whl", hash = "sha256:394fc5c42a333c9ffc3e421a4c85e08580d990e08b99f6bf35b4132114c5dcb3" },
]
[[package]]
name = "opentelemetry-api"
version = "1.39.0"
source = { registry = "https://mirrors.aliyun.com/pypi/simple" }
dependencies = [
{ name = "importlib-metadata" },
{ name = "typing-extensions" },
]
sdist = { url = "https://mirrors.aliyun.com/pypi/packages/c0/0b/e5428c009d4d9af0515b0a8371a8aaae695371af291f45e702f7969dce6b/opentelemetry_api-1.39.0.tar.gz", hash = "sha256:6130644268c5ac6bdffaf660ce878f10906b3e789f7e2daa5e169b047a2933b9" }
wheels = [
{ url = "https://mirrors.aliyun.com/pypi/packages/05/85/d831a9bc0a9e0e1a304ff3d12c1489a5fbc9bf6690a15dcbdae372bbca45/opentelemetry_api-1.39.0-py3-none-any.whl", hash = "sha256:3c3b3ca5c5687b1b5b37e5c5027ff68eacea8675241b29f13110a8ffbb8f0459" },
]
[[package]]
name = "opentelemetry-exporter-otlp-proto-common"
version = "1.39.0"
source = { registry = "https://mirrors.aliyun.com/pypi/simple" }
dependencies = [
{ name = "opentelemetry-proto" },
]
sdist = { url = "https://mirrors.aliyun.com/pypi/packages/11/cb/3a29ce606b10c76d413d6edd42d25a654af03e73e50696611e757d2602f3/opentelemetry_exporter_otlp_proto_common-1.39.0.tar.gz", hash = "sha256:a135fceed1a6d767f75be65bd2845da344dd8b9258eeed6bc48509d02b184409" }
wheels = [
{ url = "https://mirrors.aliyun.com/pypi/packages/ef/c6/215edba62d13a3948c718b289539f70e40965bc37fc82ecd55bb0b749c1a/opentelemetry_exporter_otlp_proto_common-1.39.0-py3-none-any.whl", hash = "sha256:3d77be7c4bdf90f1a76666c934368b8abed730b5c6f0547a2ec57feb115849ac" },
]
[[package]]
name = "opentelemetry-exporter-otlp-proto-grpc"
version = "1.39.0"
source = { registry = "https://mirrors.aliyun.com/pypi/simple" }
dependencies = [
{ name = "googleapis-common-protos" },
{ name = "grpcio" },
{ name = "opentelemetry-api" },
{ name = "opentelemetry-exporter-otlp-proto-common" },
{ name = "opentelemetry-proto" },
{ name = "opentelemetry-sdk" },
{ name = "typing-extensions" },
]
sdist = { url = "https://mirrors.aliyun.com/pypi/packages/7e/62/4db083ee9620da3065eeb559e9fc128f41a1d15e7c48d7c83aafbccd354c/opentelemetry_exporter_otlp_proto_grpc-1.39.0.tar.gz", hash = "sha256:7e7bb3f436006836c0e0a42ac619097746ad5553ad7128a5bd4d3e727f37fc06" }
wheels = [
{ url = "https://mirrors.aliyun.com/pypi/packages/56/e8/d420b94ffddfd8cff85bb4aa5d98da26ce7935dc3cf3eca6b83cd39ab436/opentelemetry_exporter_otlp_proto_grpc-1.39.0-py3-none-any.whl", hash = "sha256:758641278050de9bb895738f35ff8840e4a47685b7e6ef4a201fe83196ba7a05" },
]
[[package]]
name = "opentelemetry-instrumentation"
version = "0.60b0"
source = { registry = "https://mirrors.aliyun.com/pypi/simple" }
dependencies = [
{ name = "opentelemetry-api" },
{ name = "opentelemetry-semantic-conventions" },
{ name = "packaging" },
{ name = "wrapt" },
]
sdist = { url = "https://mirrors.aliyun.com/pypi/packages/55/3c/bd53dbb42eff93d18e3047c7be11224aa9966ce98ac4cc5bfb860a32c95a/opentelemetry_instrumentation-0.60b0.tar.gz", hash = "sha256:4e9fec930f283a2677a2217754b40aaf9ef76edae40499c165bc7f1d15366a74" }
wheels = [
{ url = "https://mirrors.aliyun.com/pypi/packages/5c/7b/5b5b9f8cfe727a28553acf9cd287b1d7f706f5c0a00d6e482df55b169483/opentelemetry_instrumentation-0.60b0-py3-none-any.whl", hash = "sha256:aaafa1483543a402819f1bdfb06af721c87d60dd109501f9997332862a35c76a" },
]
[[package]]
name = "opentelemetry-instrumentation-asgi"
version = "0.60b0"
source = { registry = "https://mirrors.aliyun.com/pypi/simple" }
dependencies = [
{ name = "asgiref" },
{ name = "opentelemetry-api" },
{ name = "opentelemetry-instrumentation" },
{ name = "opentelemetry-semantic-conventions" },
{ name = "opentelemetry-util-http" },
]
sdist = { url = "https://mirrors.aliyun.com/pypi/packages/b0/0a/715ea7044708d3c215385fb2a1c6ffe429aacb3cd23a348060aaeda52834/opentelemetry_instrumentation_asgi-0.60b0.tar.gz", hash = "sha256:928731218050089dca69f0fe980b8bfe109f384be8b89802d7337372ddb67b91" }
wheels = [
{ url = "https://mirrors.aliyun.com/pypi/packages/9b/8c/c6c59127fd996107243ca45669355665a7daff578ddafb86d6d2d3b01428/opentelemetry_instrumentation_asgi-0.60b0-py3-none-any.whl", hash = "sha256:9d76a541269452c718a0384478f3291feb650c5a3f29e578fdc6613ea3729cf3" },
]
[[package]]
name = "opentelemetry-instrumentation-fastapi"
version = "0.60b0"
source = { registry = "https://mirrors.aliyun.com/pypi/simple" }
dependencies = [
{ name = "opentelemetry-api" },
{ name = "opentelemetry-instrumentation" },
{ name = "opentelemetry-instrumentation-asgi" },
{ name = "opentelemetry-semantic-conventions" },
{ name = "opentelemetry-util-http" },
]
sdist = { url = "https://mirrors.aliyun.com/pypi/packages/fe/51/a021a7c929b5103fcb6bfdfa5a99abcaeb3b505faf9e3ee3ec14612c1ef9/opentelemetry_instrumentation_fastapi-0.60b0.tar.gz", hash = "sha256:5d34d67eb634a08bfe9e530680d6177521cd9da79285144e6d5a8f42683ed1b3" }
wheels = [
{ url = "https://mirrors.aliyun.com/pypi/packages/b1/5a/e238c108eb65a726d75184439377a87d532050036b54e718e4c789b26d1a/opentelemetry_instrumentation_fastapi-0.60b0-py3-none-any.whl", hash = "sha256:415c6602db01ee339276ea4cabe3e80177c9e955631c087f2ef60a75e31bfaee" },
]
[[package]]
name = "opentelemetry-instrumentation-logging"
version = "0.60b0"
source = { registry = "https://mirrors.aliyun.com/pypi/simple" }
dependencies = [
{ name = "opentelemetry-api" },
{ name = "opentelemetry-instrumentation" },
]
sdist = { url = "https://mirrors.aliyun.com/pypi/packages/5b/8b/a1aed0b695a58a1f0bdcf90fae5e468cc0fd7de2b74b9816b17e45c38e43/opentelemetry_instrumentation_logging-0.60b0.tar.gz", hash = "sha256:6d87840666669cbbcd53d2230c7a33476862d0bf7f1adc67a95519c6ccfc8281" }
wheels = [
{ url = "https://mirrors.aliyun.com/pypi/packages/00/89/6d4f5d8d03376637bff5b8d9e91356104a6f1ce9a34a2099bb2f4bf5e2b5/opentelemetry_instrumentation_logging-0.60b0-py3-none-any.whl", hash = "sha256:af75b3020911b9b6a1b4b19819a165eb131ce9bfdd313062d578fc2dc9a5cd0f" },
]
[[package]]
name = "opentelemetry-instrumentation-sqlalchemy"
version = "0.60b0"
source = { registry = "https://mirrors.aliyun.com/pypi/simple" }
dependencies = [
{ name = "opentelemetry-api" },
{ name = "opentelemetry-instrumentation" },
{ name = "opentelemetry-semantic-conventions" },
{ name = "packaging" },
{ name = "wrapt" },
]
sdist = { url = "https://mirrors.aliyun.com/pypi/packages/8f/52/6a6e8ef8d0430487f1c65fdb81f2001d0b3b68de72f7437b54ff2330de44/opentelemetry_instrumentation_sqlalchemy-0.60b0.tar.gz", hash = "sha256:df9fdc6f48709138343971cef95a055f52d0262331115231bd5d678c1a452891" }
wheels = [
{ url = "https://mirrors.aliyun.com/pypi/packages/e0/08/943c1c650e7826b0462f0a2528d37b9cf717957955df6259b9c25dfcaa51/opentelemetry_instrumentation_sqlalchemy-0.60b0-py3-none-any.whl", hash = "sha256:ff66ac39364bfb38fe127f823b36693c6f2a44f929926863640ac1575583a73f" },
]
[[package]]
name = "opentelemetry-proto"
version = "1.39.0"
source = { registry = "https://mirrors.aliyun.com/pypi/simple" }
dependencies = [
{ name = "protobuf" },
]
sdist = { url = "https://mirrors.aliyun.com/pypi/packages/48/b5/64d2f8c3393cd13ea2092106118f7b98461ba09333d40179a31444c6f176/opentelemetry_proto-1.39.0.tar.gz", hash = "sha256:c1fa48678ad1a1624258698e59be73f990b7fc1f39e73e16a9d08eef65dd838c" }
wheels = [
{ url = "https://mirrors.aliyun.com/pypi/packages/e3/4d/d500e1862beed68318705732d1976c390f4a72ca8009c4983ff627acff20/opentelemetry_proto-1.39.0-py3-none-any.whl", hash = "sha256:1e086552ac79acb501485ff0ce75533f70f3382d43d0a30728eeee594f7bf818" },
]
[[package]]
name = "opentelemetry-sdk"
version = "1.39.0"
source = { registry = "https://mirrors.aliyun.com/pypi/simple" }
dependencies = [
{ name = "opentelemetry-api" },
{ name = "opentelemetry-semantic-conventions" },
{ name = "typing-extensions" },
]
sdist = { url = "https://mirrors.aliyun.com/pypi/packages/51/e3/7cd989003e7cde72e0becfe830abff0df55c69d237ee7961a541e0167833/opentelemetry_sdk-1.39.0.tar.gz", hash = "sha256:c22204f12a0529e07aa4d985f1bca9d6b0e7b29fe7f03e923548ae52e0e15dde" }
wheels = [
{ url = "https://mirrors.aliyun.com/pypi/packages/a4/b4/2adc8bc83eb1055ecb592708efb6f0c520cc2eb68970b02b0f6ecda149cf/opentelemetry_sdk-1.39.0-py3-none-any.whl", hash = "sha256:90cfb07600dfc0d2de26120cebc0c8f27e69bf77cd80ef96645232372709a514" },
]
[[package]]
name = "opentelemetry-semantic-conventions"
version = "0.60b0"
source = { registry = "https://mirrors.aliyun.com/pypi/simple" }
dependencies = [
{ name = "opentelemetry-api" },
{ name = "typing-extensions" },
]
sdist = { url = "https://mirrors.aliyun.com/pypi/packages/71/0e/176a7844fe4e3cb5de604212094dffaed4e18b32f1c56b5258bcbcba85c2/opentelemetry_semantic_conventions-0.60b0.tar.gz", hash = "sha256:227d7aa73cbb8a2e418029d6b6465553aa01cf7e78ec9d0bc3255c7b3ac5bf8f" }
wheels = [
{ url = "https://mirrors.aliyun.com/pypi/packages/d0/56/af0306666f91bae47db14d620775604688361f0f76a872e0005277311131/opentelemetry_semantic_conventions-0.60b0-py3-none-any.whl", hash = "sha256:069530852691136018087b52688857d97bba61cd641d0f8628d2d92788c4f78a" },
]
[[package]]
name = "opentelemetry-util-http"
version = "0.60b0"
source = { registry = "https://mirrors.aliyun.com/pypi/simple" }
sdist = { url = "https://mirrors.aliyun.com/pypi/packages/38/0d/786a713445cf338131fef3a84fab1378e4b2ef3c3ea348eeb0c915eb804a/opentelemetry_util_http-0.60b0.tar.gz", hash = "sha256:e42b7bb49bba43b6f34390327d97e5016eb1c47949ceaf37c4795472a4e3a82d" }
wheels = [
{ url = "https://mirrors.aliyun.com/pypi/packages/53/5d/a448862f6d10c95685ed0e703596b6bd1784074e7ad90bffdc550abb7b68/opentelemetry_util_http-0.60b0-py3-none-any.whl", hash = "sha256:4f366f1a48adb74ffa6f80aee26f96882e767e01b03cd1cfb948b6e1020341fe" },
]
[[package]]
name = "packaging"
version = "25.0"
@@ -1900,6 +2164,21 @@ wheels = [
{ url = "https://mirrors.aliyun.com/pypi/packages/5b/5a/bc7b4a4ef808fa59a816c17b20c4bef6884daebbdf627ff2a161da67da19/propcache-0.4.1-py3-none-any.whl", hash = "sha256:af2a6052aeb6cf17d3e46ee169099044fd8224cbaf75c76a2ef596e8163e2237" },
]
[[package]]
name = "protobuf"
version = "6.33.2"
source = { registry = "https://mirrors.aliyun.com/pypi/simple" }
sdist = { url = "https://mirrors.aliyun.com/pypi/packages/34/44/e49ecff446afeec9d1a66d6bbf9adc21e3c7cea7803a920ca3773379d4f6/protobuf-6.33.2.tar.gz", hash = "sha256:56dc370c91fbb8ac85bc13582c9e373569668a290aa2e66a590c2a0d35ddb9e4" }
wheels = [
{ url = "https://mirrors.aliyun.com/pypi/packages/bc/91/1e3a34881a88697a7354ffd177e8746e97a722e5e8db101544b47e84afb1/protobuf-6.33.2-cp310-abi3-win32.whl", hash = "sha256:87eb388bd2d0f78febd8f4c8779c79247b26a5befad525008e49a6955787ff3d" },
{ url = "https://mirrors.aliyun.com/pypi/packages/64/20/4d50191997e917ae13ad0a235c8b42d8c1ab9c3e6fd455ca16d416944355/protobuf-6.33.2-cp310-abi3-win_amd64.whl", hash = "sha256:fc2a0e8b05b180e5fc0dd1559fe8ebdae21a27e81ac77728fb6c42b12c7419b4" },
{ url = "https://mirrors.aliyun.com/pypi/packages/b2/ca/7e485da88ba45c920fb3f50ae78de29ab925d9e54ef0de678306abfbb497/protobuf-6.33.2-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:d9b19771ca75935b3a4422957bc518b0cecb978b31d1dd12037b088f6bcc0e43" },
{ url = "https://mirrors.aliyun.com/pypi/packages/7d/4f/f743761e41d3b2b2566748eb76bbff2b43e14d5fcab694f494a16458b05f/protobuf-6.33.2-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:b5d3b5625192214066d99b2b605f5783483575656784de223f00a8d00754fc0e" },
{ url = "https://mirrors.aliyun.com/pypi/packages/b1/fa/26468d00a92824020f6f2090d827078c09c9c587e34cbfd2d0c7911221f8/protobuf-6.33.2-cp39-abi3-manylinux2014_s390x.whl", hash = "sha256:8cd7640aee0b7828b6d03ae518b5b4806fdfc1afe8de82f79c3454f8aef29872" },
{ url = "https://mirrors.aliyun.com/pypi/packages/56/13/333b8f421738f149d4fe5e49553bc2a2ab75235486259f689b4b91f96cec/protobuf-6.33.2-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:1f8017c48c07ec5859106533b682260ba3d7c5567b1ca1f24297ce03384d1b4f" },
{ url = "https://mirrors.aliyun.com/pypi/packages/0e/15/4f02896cc3df04fc465010a4c6a0cd89810f54617a32a70ef531ed75d61c/protobuf-6.33.2-py3-none-any.whl", hash = "sha256:7636aad9bb01768870266de5dc009de2d1b936771b38a793f73cbbf279c91c5c" },
]
[[package]]
name = "psutil"
version = "7.1.3"
@@ -3073,6 +3352,75 @@ wheels = [
{ url = "https://mirrors.aliyun.com/pypi/packages/e1/07/c6fe3ad3e685340704d314d765b7912993bcb8dc198f0e7a89382d37974b/win32_setctime-1.2.0-py3-none-any.whl", hash = "sha256:95d644c4e708aba81dc3704a116d8cbc974d70b3bdb8be1d150e36be6e9d1390" },
]
[[package]]
name = "wrapt"
version = "1.17.3"
source = { registry = "https://mirrors.aliyun.com/pypi/simple" }
sdist = { url = "https://mirrors.aliyun.com/pypi/packages/95/8f/aeb76c5b46e273670962298c23e7ddde79916cb74db802131d49a85e4b7d/wrapt-1.17.3.tar.gz", hash = "sha256:f66eb08feaa410fe4eebd17f2a2c8e2e46d3476e9f8c783daa8e09e0faa666d0" }
wheels = [
{ url = "https://mirrors.aliyun.com/pypi/packages/3f/23/bb82321b86411eb51e5a5db3fb8f8032fd30bd7c2d74bfe936136b2fa1d6/wrapt-1.17.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:88bbae4d40d5a46142e70d58bf664a89b6b4befaea7b2ecc14e03cedb8e06c04" },
{ url = "https://mirrors.aliyun.com/pypi/packages/45/69/f3c47642b79485a30a59c63f6d739ed779fb4cc8323205d047d741d55220/wrapt-1.17.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6b13af258d6a9ad602d57d889f83b9d5543acd471eee12eb51f5b01f8eb1bc2" },
{ url = "https://mirrors.aliyun.com/pypi/packages/d1/71/e7e7f5670c1eafd9e990438e69d8fb46fa91a50785332e06b560c869454f/wrapt-1.17.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd341868a4b6714a5962c1af0bd44f7c404ef78720c7de4892901e540417111c" },
{ url = "https://mirrors.aliyun.com/pypi/packages/de/17/9f8f86755c191d6779d7ddead1a53c7a8aa18bccb7cea8e7e72dfa6a8a09/wrapt-1.17.3-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f9b2601381be482f70e5d1051a5965c25fb3625455a2bf520b5a077b22afb775" },
{ url = "https://mirrors.aliyun.com/pypi/packages/f2/15/dd576273491f9f43dd09fce517f6c2ce6eb4fe21681726068db0d0467096/wrapt-1.17.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:343e44b2a8e60e06a7e0d29c1671a0d9951f59174f3709962b5143f60a2a98bd" },
{ url = "https://mirrors.aliyun.com/pypi/packages/0c/c4/5eb4ce0d4814521fee7aa806264bf7a114e748ad05110441cd5b8a5c744b/wrapt-1.17.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:33486899acd2d7d3066156b03465b949da3fd41a5da6e394ec49d271baefcf05" },
{ url = "https://mirrors.aliyun.com/pypi/packages/31/4b/819e9e0eb5c8dc86f60dfc42aa4e2c0d6c3db8732bce93cc752e604bb5f5/wrapt-1.17.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e6f40a8aa5a92f150bdb3e1c44b7e98fb7113955b2e5394122fa5532fec4b418" },
{ url = "https://mirrors.aliyun.com/pypi/packages/f8/83/ed6baf89ba3a56694700139698cf703aac9f0f9eb03dab92f57551bd5385/wrapt-1.17.3-cp310-cp310-win32.whl", hash = "sha256:a36692b8491d30a8c75f1dfee65bef119d6f39ea84ee04d9f9311f83c5ad9390" },
{ url = "https://mirrors.aliyun.com/pypi/packages/2f/90/ee61d36862340ad7e9d15a02529df6b948676b9a5829fd5e16640156627d/wrapt-1.17.3-cp310-cp310-win_amd64.whl", hash = "sha256:afd964fd43b10c12213574db492cb8f73b2f0826c8df07a68288f8f19af2ebe6" },
{ url = "https://mirrors.aliyun.com/pypi/packages/bd/c3/cefe0bd330d389c9983ced15d326f45373f4073c9f4a8c2f99b50bfea329/wrapt-1.17.3-cp310-cp310-win_arm64.whl", hash = "sha256:af338aa93554be859173c39c85243970dc6a289fa907402289eeae7543e1ae18" },
{ url = "https://mirrors.aliyun.com/pypi/packages/52/db/00e2a219213856074a213503fdac0511203dceefff26e1daa15250cc01a0/wrapt-1.17.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:273a736c4645e63ac582c60a56b0acb529ef07f78e08dc6bfadf6a46b19c0da7" },
{ url = "https://mirrors.aliyun.com/pypi/packages/5e/30/ca3c4a5eba478408572096fe9ce36e6e915994dd26a4e9e98b4f729c06d9/wrapt-1.17.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5531d911795e3f935a9c23eb1c8c03c211661a5060aab167065896bbf62a5f85" },
{ url = "https://mirrors.aliyun.com/pypi/packages/31/25/3e8cc2c46b5329c5957cec959cb76a10718e1a513309c31399a4dad07eb3/wrapt-1.17.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0610b46293c59a3adbae3dee552b648b984176f8562ee0dba099a56cfbe4df1f" },
{ url = "https://mirrors.aliyun.com/pypi/packages/5d/8f/a32a99fc03e4b37e31b57cb9cefc65050ea08147a8ce12f288616b05ef54/wrapt-1.17.3-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b32888aad8b6e68f83a8fdccbf3165f5469702a7544472bdf41f582970ed3311" },
{ url = "https://mirrors.aliyun.com/pypi/packages/31/57/4930cb8d9d70d59c27ee1332a318c20291749b4fba31f113c2f8ac49a72e/wrapt-1.17.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cccf4f81371f257440c88faed6b74f1053eef90807b77e31ca057b2db74edb1" },
{ url = "https://mirrors.aliyun.com/pypi/packages/a8/f3/1afd48de81d63dd66e01b263a6fbb86e1b5053b419b9b33d13e1f6d0f7d0/wrapt-1.17.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8a210b158a34164de8bb68b0e7780041a903d7b00c87e906fb69928bf7890d5" },
{ url = "https://mirrors.aliyun.com/pypi/packages/1e/d7/4ad5327612173b144998232f98a85bb24b60c352afb73bc48e3e0d2bdc4e/wrapt-1.17.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:79573c24a46ce11aab457b472efd8d125e5a51da2d1d24387666cd85f54c05b2" },
{ url = "https://mirrors.aliyun.com/pypi/packages/bb/59/e0adfc831674a65694f18ea6dc821f9fcb9ec82c2ce7e3d73a88ba2e8718/wrapt-1.17.3-cp311-cp311-win32.whl", hash = "sha256:c31eebe420a9a5d2887b13000b043ff6ca27c452a9a22fa71f35f118e8d4bf89" },
{ url = "https://mirrors.aliyun.com/pypi/packages/83/88/16b7231ba49861b6f75fc309b11012ede4d6b0a9c90969d9e0db8d991aeb/wrapt-1.17.3-cp311-cp311-win_amd64.whl", hash = "sha256:0b1831115c97f0663cb77aa27d381237e73ad4f721391a9bfb2fe8bc25fa6e77" },
{ url = "https://mirrors.aliyun.com/pypi/packages/9a/1e/c4d4f3398ec073012c51d1c8d87f715f56765444e1a4b11e5180577b7e6e/wrapt-1.17.3-cp311-cp311-win_arm64.whl", hash = "sha256:5a7b3c1ee8265eb4c8f1b7d29943f195c00673f5ab60c192eba2d4a7eae5f46a" },
{ url = "https://mirrors.aliyun.com/pypi/packages/9f/41/cad1aba93e752f1f9268c77270da3c469883d56e2798e7df6240dcb2287b/wrapt-1.17.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ab232e7fdb44cdfbf55fc3afa31bcdb0d8980b9b95c38b6405df2acb672af0e0" },
{ url = "https://mirrors.aliyun.com/pypi/packages/60/f8/096a7cc13097a1869fe44efe68dace40d2a16ecb853141394047f0780b96/wrapt-1.17.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9baa544e6acc91130e926e8c802a17f3b16fbea0fd441b5a60f5cf2cc5c3deba" },
{ url = "https://mirrors.aliyun.com/pypi/packages/33/df/bdf864b8997aab4febb96a9ae5c124f700a5abd9b5e13d2a3214ec4be705/wrapt-1.17.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6b538e31eca1a7ea4605e44f81a48aa24c4632a277431a6ed3f328835901f4fd" },
{ url = "https://mirrors.aliyun.com/pypi/packages/9f/81/5d931d78d0eb732b95dc3ddaeeb71c8bb572fb01356e9133916cd729ecdd/wrapt-1.17.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:042ec3bb8f319c147b1301f2393bc19dba6e176b7da446853406d041c36c7828" },
{ url = "https://mirrors.aliyun.com/pypi/packages/ca/38/2e1785df03b3d72d34fc6252d91d9d12dc27a5c89caef3335a1bbb8908ca/wrapt-1.17.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3af60380ba0b7b5aeb329bc4e402acd25bd877e98b3727b0135cb5c2efdaefe9" },
{ url = "https://mirrors.aliyun.com/pypi/packages/b3/8b/48cdb60fe0603e34e05cffda0b2a4adab81fd43718e11111a4b0100fd7c1/wrapt-1.17.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b02e424deef65c9f7326d8c19220a2c9040c51dc165cddb732f16198c168396" },
{ url = "https://mirrors.aliyun.com/pypi/packages/3c/51/d81abca783b58f40a154f1b2c56db1d2d9e0d04fa2d4224e357529f57a57/wrapt-1.17.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:74afa28374a3c3a11b3b5e5fca0ae03bef8450d6aa3ab3a1e2c30e3a75d023dc" },
{ url = "https://mirrors.aliyun.com/pypi/packages/9e/b1/43b286ca1392a006d5336412d41663eeef1ad57485f3e52c767376ba7e5a/wrapt-1.17.3-cp312-cp312-win32.whl", hash = "sha256:4da9f45279fff3543c371d5ababc57a0384f70be244de7759c85a7f989cb4ebe" },
{ url = "https://mirrors.aliyun.com/pypi/packages/28/de/49493f962bd3c586ab4b88066e967aa2e0703d6ef2c43aa28cb83bf7b507/wrapt-1.17.3-cp312-cp312-win_amd64.whl", hash = "sha256:e71d5c6ebac14875668a1e90baf2ea0ef5b7ac7918355850c0908ae82bcb297c" },
{ url = "https://mirrors.aliyun.com/pypi/packages/f1/48/0f7102fe9cb1e8a5a77f80d4f0956d62d97034bbe88d33e94699f99d181d/wrapt-1.17.3-cp312-cp312-win_arm64.whl", hash = "sha256:604d076c55e2fdd4c1c03d06dc1a31b95130010517b5019db15365ec4a405fc6" },
{ url = "https://mirrors.aliyun.com/pypi/packages/fc/f6/759ece88472157acb55fc195e5b116e06730f1b651b5b314c66291729193/wrapt-1.17.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a47681378a0439215912ef542c45a783484d4dd82bac412b71e59cf9c0e1cea0" },
{ url = "https://mirrors.aliyun.com/pypi/packages/4f/a9/49940b9dc6d47027dc850c116d79b4155f15c08547d04db0f07121499347/wrapt-1.17.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:54a30837587c6ee3cd1a4d1c2ec5d24e77984d44e2f34547e2323ddb4e22eb77" },
{ url = "https://mirrors.aliyun.com/pypi/packages/45/35/6a08de0f2c96dcdd7fe464d7420ddb9a7655a6561150e5fc4da9356aeaab/wrapt-1.17.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:16ecf15d6af39246fe33e507105d67e4b81d8f8d2c6598ff7e3ca1b8a37213f7" },
{ url = "https://mirrors.aliyun.com/pypi/packages/0c/37/6faf15cfa41bf1f3dba80cd3f5ccc6622dfccb660ab26ed79f0178c7497f/wrapt-1.17.3-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6fd1ad24dc235e4ab88cda009e19bf347aabb975e44fd5c2fb22a3f6e4141277" },
{ url = "https://mirrors.aliyun.com/pypi/packages/78/f2/efe19ada4a38e4e15b6dff39c3e3f3f73f5decf901f66e6f72fe79623a06/wrapt-1.17.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ed61b7c2d49cee3c027372df5809a59d60cf1b6c2f81ee980a091f3afed6a2d" },
{ url = "https://mirrors.aliyun.com/pypi/packages/40/90/ca86701e9de1622b16e09689fc24b76f69b06bb0150990f6f4e8b0eeb576/wrapt-1.17.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:423ed5420ad5f5529db9ce89eac09c8a2f97da18eb1c870237e84c5a5c2d60aa" },
{ url = "https://mirrors.aliyun.com/pypi/packages/fd/e0/d10bd257c9a3e15cbf5523025252cc14d77468e8ed644aafb2d6f54cb95d/wrapt-1.17.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e01375f275f010fcbf7f643b4279896d04e571889b8a5b3f848423d91bf07050" },
{ url = "https://mirrors.aliyun.com/pypi/packages/e8/cf/7d848740203c7b4b27eb55dbfede11aca974a51c3d894f6cc4b865f42f58/wrapt-1.17.3-cp313-cp313-win32.whl", hash = "sha256:53e5e39ff71b3fc484df8a522c933ea2b7cdd0d5d15ae82e5b23fde87d44cbd8" },
{ url = "https://mirrors.aliyun.com/pypi/packages/57/54/35a84d0a4d23ea675994104e667ceff49227ce473ba6a59ba2c84f250b74/wrapt-1.17.3-cp313-cp313-win_amd64.whl", hash = "sha256:1f0b2f40cf341ee8cc1a97d51ff50dddb9fcc73241b9143ec74b30fc4f44f6cb" },
{ url = "https://mirrors.aliyun.com/pypi/packages/01/77/66e54407c59d7b02a3c4e0af3783168fff8e5d61def52cda8728439d86bc/wrapt-1.17.3-cp313-cp313-win_arm64.whl", hash = "sha256:7425ac3c54430f5fc5e7b6f41d41e704db073309acfc09305816bc6a0b26bb16" },
{ url = "https://mirrors.aliyun.com/pypi/packages/02/a2/cd864b2a14f20d14f4c496fab97802001560f9f41554eef6df201cd7f76c/wrapt-1.17.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:cf30f6e3c077c8e6a9a7809c94551203c8843e74ba0c960f4a98cd80d4665d39" },
{ url = "https://mirrors.aliyun.com/pypi/packages/d5/46/d011725b0c89e853dc44cceb738a307cde5d240d023d6d40a82d1b4e1182/wrapt-1.17.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:e228514a06843cae89621384cfe3a80418f3c04aadf8a3b14e46a7be704e4235" },
{ url = "https://mirrors.aliyun.com/pypi/packages/2e/9e/3ad852d77c35aae7ddebdbc3b6d35ec8013af7d7dddad0ad911f3d891dae/wrapt-1.17.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:5ea5eb3c0c071862997d6f3e02af1d055f381b1d25b286b9d6644b79db77657c" },
{ url = "https://mirrors.aliyun.com/pypi/packages/c3/f7/c983d2762bcce2326c317c26a6a1e7016f7eb039c27cdf5c4e30f4160f31/wrapt-1.17.3-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:281262213373b6d5e4bb4353bc36d1ba4084e6d6b5d242863721ef2bf2c2930b" },
{ url = "https://mirrors.aliyun.com/pypi/packages/e4/0f/f673f75d489c7f22d17fe0193e84b41540d962f75fce579cf6873167c29b/wrapt-1.17.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc4a8d2b25efb6681ecacad42fca8859f88092d8732b170de6a5dddd80a1c8fa" },
{ url = "https://mirrors.aliyun.com/pypi/packages/df/61/515ad6caca68995da2fac7a6af97faab8f78ebe3bf4f761e1b77efbc47b5/wrapt-1.17.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:373342dd05b1d07d752cecbec0c41817231f29f3a89aa8b8843f7b95992ed0c7" },
{ url = "https://mirrors.aliyun.com/pypi/packages/d3/bd/4e70162ce398462a467bc09e768bee112f1412e563620adc353de9055d33/wrapt-1.17.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d40770d7c0fd5cbed9d84b2c3f2e156431a12c9a37dc6284060fb4bec0b7ffd4" },
{ url = "https://mirrors.aliyun.com/pypi/packages/2b/b8/da8560695e9284810b8d3df8a19396a6e40e7518059584a1a394a2b35e0a/wrapt-1.17.3-cp314-cp314-win32.whl", hash = "sha256:fbd3c8319de8e1dc79d346929cd71d523622da527cca14e0c1d257e31c2b8b10" },
{ url = "https://mirrors.aliyun.com/pypi/packages/db/c8/b71eeb192c440d67a5a0449aaee2310a1a1e8eca41676046f99ed2487e9f/wrapt-1.17.3-cp314-cp314-win_amd64.whl", hash = "sha256:e1a4120ae5705f673727d3253de3ed0e016f7cd78dc463db1b31e2463e1f3cf6" },
{ url = "https://mirrors.aliyun.com/pypi/packages/45/20/2cda20fd4865fa40f86f6c46ed37a2a8356a7a2fde0773269311f2af56c7/wrapt-1.17.3-cp314-cp314-win_arm64.whl", hash = "sha256:507553480670cab08a800b9463bdb881b2edeed77dc677b0a5915e6106e91a58" },
{ url = "https://mirrors.aliyun.com/pypi/packages/77/ed/dd5cf21aec36c80443c6f900449260b80e2a65cf963668eaef3b9accce36/wrapt-1.17.3-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:ed7c635ae45cfbc1a7371f708727bf74690daedc49b4dba310590ca0bd28aa8a" },
{ url = "https://mirrors.aliyun.com/pypi/packages/8d/96/450c651cc753877ad100c7949ab4d2e2ecc4d97157e00fa8f45df682456a/wrapt-1.17.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:249f88ed15503f6492a71f01442abddd73856a0032ae860de6d75ca62eed8067" },
{ url = "https://mirrors.aliyun.com/pypi/packages/d1/86/2fcad95994d9b572db57632acb6f900695a648c3e063f2cd344b3f5c5a37/wrapt-1.17.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a03a38adec8066d5a37bea22f2ba6bbf39fcdefbe2d91419ab864c3fb515454" },
{ url = "https://mirrors.aliyun.com/pypi/packages/64/0e/f4472f2fdde2d4617975144311f8800ef73677a159be7fe61fa50997d6c0/wrapt-1.17.3-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5d4478d72eb61c36e5b446e375bbc49ed002430d17cdec3cecb36993398e1a9e" },
{ url = "https://mirrors.aliyun.com/pypi/packages/cc/01/9b85a99996b0a97c8a17484684f206cbb6ba73c1ce6890ac668bcf3838fb/wrapt-1.17.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:223db574bb38637e8230eb14b185565023ab624474df94d2af18f1cdb625216f" },
{ url = "https://mirrors.aliyun.com/pypi/packages/25/02/78926c1efddcc7b3aa0bc3d6b33a822f7d898059f7cd9ace8c8318e559ef/wrapt-1.17.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e405adefb53a435f01efa7ccdec012c016b5a1d3f35459990afc39b6be4d5056" },
{ url = "https://mirrors.aliyun.com/pypi/packages/dc/ee/c414501ad518ac3e6fe184753632fe5e5ecacdcf0effc23f31c1e4f7bfcf/wrapt-1.17.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:88547535b787a6c9ce4086917b6e1d291aa8ed914fdd3a838b3539dc95c12804" },
{ url = "https://mirrors.aliyun.com/pypi/packages/be/44/a1bd64b723d13bb151d6cc91b986146a1952385e0392a78567e12149c7b4/wrapt-1.17.3-cp314-cp314t-win32.whl", hash = "sha256:41b1d2bc74c2cac6f9074df52b2efbef2b30bdfe5f40cb78f8ca22963bc62977" },
{ url = "https://mirrors.aliyun.com/pypi/packages/79/d9/7cfd5a312760ac4dd8bf0184a6ee9e43c33e47f3dadc303032ce012b8fa3/wrapt-1.17.3-cp314-cp314t-win_amd64.whl", hash = "sha256:73d496de46cd2cdbdbcce4ae4bcdb4afb6a11234a1df9c085249d55166b95116" },
{ url = "https://mirrors.aliyun.com/pypi/packages/46/78/10ad9781128ed2f99dbc474f43283b13fea8ba58723e98844367531c18e9/wrapt-1.17.3-cp314-cp314t-win_arm64.whl", hash = "sha256:f38e60678850c42461d4202739f9bf1e3a737c7ad283638251e79cc49effb6b6" },
{ url = "https://mirrors.aliyun.com/pypi/packages/1f/f6/a933bd70f98e9cf3e08167fc5cd7aaaca49147e48411c0bd5ae701bb2194/wrapt-1.17.3-py3-none-any.whl", hash = "sha256:7171ae35d2c33d326ac19dd8facb1e82e5fd04ef8c6c0e394d7af55a55051c22" },
]
[[package]]
name = "wsproto"
version = "1.3.2"
@@ -3211,6 +3559,15 @@ wheels = [
{ url = "https://mirrors.aliyun.com/pypi/packages/73/ae/b48f95715333080afb75a4504487cbe142cae1268afc482d06692d605ae6/yarl-1.22.0-py3-none-any.whl", hash = "sha256:1380560bdba02b6b6c90de54133c81c9f2a453dee9912fe58c1dcced1edb7cff" },
]
[[package]]
name = "zipp"
version = "3.23.0"
source = { registry = "https://mirrors.aliyun.com/pypi/simple" }
sdist = { url = "https://mirrors.aliyun.com/pypi/packages/e3/02/0f2892c661036d50ede074e376733dca2ae7c6eb617489437771209d4180/zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166" }
wheels = [
{ url = "https://mirrors.aliyun.com/pypi/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e" },
]
[[package]]
name = "zope-event"
version = "6.1"