feat: add postgres telemetry recorder with two-tier degradation

This commit is contained in:
2026-07-21 00:50:33 -04:00
parent 0e22fcf433
commit abb65c2324
5 changed files with 359 additions and 12 deletions
+43 -11
View File
@@ -162,9 +162,13 @@ class GatewayClient:
transport_aclose = getattr(self._transport, "aclose", None)
if transport_aclose is not None:
await transport_aclose()
telemetry_close = getattr(self._telemetry, "close", None)
if telemetry_close is not None:
telemetry_close()
telemetry_aclose = getattr(self._telemetry, "aclose", None)
if telemetry_aclose is not None:
await telemetry_aclose() # Postgres 等异步后端
else:
telemetry_close = getattr(self._telemetry, "close", None)
if telemetry_close is not None:
telemetry_close()
cache_aclose = getattr(self._cache, "aclose", None)
if cache_aclose is not None:
await cache_aclose()
@@ -196,14 +200,8 @@ class GatewayClient:
scope=settings.scope,
sources=sources,
selector=_build_selector(settings.selector),
limiter=limiter
or InMemoryLimiter(
scope=settings.scope,
sources={s.name: s for s in sources},
global_limits=settings.global_limits,
lease_ttl_s=settings.lease_ttl_s,
),
breaker=breaker or InMemoryGate(config=settings.breaker),
limiter=limiter or _build_limiter(settings, sources),
breaker=breaker or _build_breaker(settings),
transport=OpenAICompatTransport(registry=registry),
retry=settings.retry,
backpressure=settings.backpressure,
@@ -240,6 +238,35 @@ class GatewayClient:
)
def _build_limiter(settings: GatewaySettings, sources: list[SourceConfig]) -> RateLimiter:
if settings.limiter_backend == "redis":
from polygateway.backends.redis.limiter import RedisLimiter
assert settings.redis_url is not None # 内部不变量: config 已校验
return RedisLimiter.from_url(
settings.redis_url,
scope=settings.scope,
sources={s.name: s for s in sources},
global_limits=settings.global_limits,
lease_ttl_s=settings.lease_ttl_s,
)
return InMemoryLimiter(
scope=settings.scope,
sources={s.name: s for s in sources},
global_limits=settings.global_limits,
lease_ttl_s=settings.lease_ttl_s,
)
def _build_breaker(settings: GatewaySettings) -> ProviderGate:
if settings.breaker_backend == "redis":
from polygateway.backends.redis.breaker import RedisGate
assert settings.redis_url is not None # 内部不变量: config 已校验
return RedisGate.from_url(settings.redis_url, config=settings.breaker, scope=settings.scope)
return InMemoryGate(config=settings.breaker)
def _build_selector(name: str) -> SourceSelector:
return RoundRobinSelector() if name == "round_robin" else LeastInflightSelector()
@@ -258,6 +285,11 @@ def _build_cache(settings: GatewaySettings) -> CacheBackend | None:
def _build_telemetry(settings: GatewaySettings) -> TelemetryRecorder | None:
if settings.telemetry_backend == "none":
return None
if settings.telemetry_backend == "postgres":
from polygateway.telemetry.postgres import PostgresRecorder
assert settings.telemetry_pg_dsn is not None # 内部不变量: config 已校验
return PostgresRecorder(settings.telemetry_pg_dsn)
from polygateway.telemetry.sqlite import SQLiteRecorder
assert settings.telemetry_sqlite_path is not None # 内部不变量: config 已校验