springbootAI 1.8.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- spring/__init__.py +66 -0
- spring/ai/__init__.py +78 -0
- spring/ai/advisors.py +139 -0
- spring/ai/annotations.py +74 -0
- spring/ai/autoconfig.py +481 -0
- spring/ai/core.py +391 -0
- spring/ai/etl.py +188 -0
- spring/ai/memory.py +109 -0
- spring/ai/observability.py +129 -0
- spring/ai/providers.py +789 -0
- spring/ai/resilience.py +258 -0
- spring/ai/tools.py +106 -0
- spring/ai/vectorstore.py +303 -0
- spring/annotations/__init__.py +188 -0
- spring/annotations/cache.py +126 -0
- spring/annotations/cloud.py +207 -0
- spring/annotations/conditional.py +272 -0
- spring/annotations/core.py +864 -0
- spring/annotations/messaging.py +107 -0
- spring/aop/__init__.py +4 -0
- spring/aop/cloud_aop.py +404 -0
- spring/aop/comprehensive_aop.py +1015 -0
- spring/aop/method_interceptor.py +19 -0
- spring/aop/proxy_factory.py +55 -0
- spring/cloud/__init__.py +76 -0
- spring/cloud/discovery.py +364 -0
- spring/cloud/feign.py +469 -0
- spring/cloud/gateway.py +452 -0
- spring/cloud/load_balancer.py +149 -0
- spring/cloud/seata.py +557 -0
- spring/cloud/sentinel.py +525 -0
- spring/cloud/tracer.py +337 -0
- spring/config/__init__.py +21 -0
- spring/config/binding.py +206 -0
- spring/config/config_loader.py +405 -0
- spring/context/__init__.py +13 -0
- spring/context/application_context.py +589 -0
- spring/context/bean_definition.py +70 -0
- spring/context/bean_factory.py +1052 -0
- spring/context/registry.py +58 -0
- spring/context/scanner.py +106 -0
- spring/core/__init__.py +3 -0
- spring/core/graceful_shutdown.py +196 -0
- spring/core/typing_utils.py +50 -0
- spring/csv/__init__.py +52 -0
- spring/csv/annotations.py +402 -0
- spring/csv/converters.py +69 -0
- spring/csv/easy_csv.py +95 -0
- spring/csv/exceptions.py +27 -0
- spring/csv/reader.py +195 -0
- spring/csv/writer.py +155 -0
- spring/data/__init__.py +54 -0
- spring/data/page.py +181 -0
- spring/data/repository.py +274 -0
- spring/data/specification.py +228 -0
- spring/datasource/__init__.py +66 -0
- spring/datasource/annotations.py +133 -0
- spring/datasource/context.py +69 -0
- spring/datasource/dynamic.py +148 -0
- spring/event/__init__.py +7 -0
- spring/event/publisher.py +69 -0
- spring/excel/__init__.py +51 -0
- spring/excel/annotations.py +405 -0
- spring/excel/converters.py +231 -0
- spring/excel/easy_excel.py +94 -0
- spring/excel/exceptions.py +31 -0
- spring/excel/reader.py +254 -0
- spring/excel/style.py +95 -0
- spring/excel/writer.py +197 -0
- spring/i18n/__init__.py +97 -0
- spring/i18n/accessor.py +94 -0
- spring/i18n/auto_config.py +177 -0
- spring/i18n/holder.py +106 -0
- spring/i18n/locale.py +152 -0
- spring/i18n/locale_resolver.py +367 -0
- spring/i18n/message_source.py +250 -0
- spring/i18n/middleware.py +79 -0
- spring/i18n/properties.py +168 -0
- spring/i18n/sources.py +255 -0
- spring/logging/__init__.py +1 -0
- spring/logging/loguru_logger.py +228 -0
- spring/main.py +378 -0
- spring/messaging/__init__.py +1 -0
- spring/messaging/rabbitmq.py +302 -0
- spring/monitoring/__init__.py +1 -0
- spring/monitoring/prometheus.py +199 -0
- spring/orm/__init__.py +258 -0
- spring/orm/database.py +222 -0
- spring/orm/ddl_auto.py +1217 -0
- spring/orm/migration.py +419 -0
- spring/orm/mybatis_integration.py +400 -0
- spring/orm/pymybatis/__init__.py +86 -0
- spring/orm/pymybatis/annotations/__init__.py +30 -0
- spring/orm/pymybatis/annotations/annotations.py +332 -0
- spring/orm/pymybatis/cache/__init__.py +47 -0
- spring/orm/pymybatis/cache/cache.py +371 -0
- spring/orm/pymybatis/cache/redis_cache.py +434 -0
- spring/orm/pymybatis/circuit_breaker/__init__.py +21 -0
- spring/orm/pymybatis/circuit_breaker/circuit_breaker.py +424 -0
- spring/orm/pymybatis/configuration.py +525 -0
- spring/orm/pymybatis/core/__init__.py +10 -0
- spring/orm/pymybatis/core/sql_session.py +1382 -0
- spring/orm/pymybatis/core/sql_session_factory.py +76 -0
- spring/orm/pymybatis/dialect/__init__.py +9 -0
- spring/orm/pymybatis/dialect/dialect.py +445 -0
- spring/orm/pymybatis/dynamic_sql/__init__.py +9 -0
- spring/orm/pymybatis/dynamic_sql/dynamic_sql.py +900 -0
- spring/orm/pymybatis/interceptor/__init__.py +31 -0
- spring/orm/pymybatis/interceptor/interceptor.py +427 -0
- spring/orm/pymybatis/mapper/__init__.py +9 -0
- spring/orm/pymybatis/mapper/mapper.py +540 -0
- spring/orm/pymybatis/metrics/__init__.py +41 -0
- spring/orm/pymybatis/metrics/metrics.py +595 -0
- spring/orm/pymybatis/pool/__init__.py +9 -0
- spring/orm/pymybatis/pool/connection_pool.py +711 -0
- spring/orm/pymybatis/security/__init__.py +19 -0
- spring/orm/pymybatis/security/access_control.py +415 -0
- spring/orm/pymybatis/security/password_encoder.py +293 -0
- spring/orm/pymybatis/security/sensitive_data_masker.py +326 -0
- spring/orm/pymybatis/security/sql_injection_detector.py +675 -0
- spring/orm/pymybatis/transaction/__init__.py +9 -0
- spring/orm/pymybatis/transaction/transaction.py +288 -0
- spring/orm/pymybatis/type_handler/__init__.py +37 -0
- spring/orm/pymybatis/type_handler/type_handler.py +473 -0
- spring/orm/pymybatis/version.py +9 -0
- spring/orm/pymybatis/xml_parser/__init__.py +9 -0
- spring/orm/pymybatis/xml_parser/xml_parser.py +761 -0
- spring/retry/__init__.py +12 -0
- spring/retry/retry_annotations.py +71 -0
- spring/retry/retry_decorator.py +155 -0
- spring/scheduling/__init__.py +3 -0
- spring/scheduling/scheduler.py +389 -0
- spring/security/__init__.py +39 -0
- spring/security/jwt_utils.py +281 -0
- spring/security/replay_protection.py +206 -0
- spring/security/secret_manager.py +226 -0
- spring/security/security_aop.py +248 -0
- spring/security/security_context.py +172 -0
- spring/test/__init__.py +45 -0
- spring/test/slicing.py +341 -0
- spring/tracing/__init__.py +11 -0
- spring/tracing/skywalking.py +229 -0
- spring/tx/__init__.py +52 -0
- spring/tx/events.py +172 -0
- spring/tx/synchronization.py +143 -0
- spring/utils/__init__.py +5 -0
- spring/utils/banner.py +32 -0
- spring/utils/logger.py +73 -0
- spring/utils/redis_client.py +526 -0
- spring/validation/__init__.py +55 -0
- spring/validation/aop.py +141 -0
- spring/validation/constraints.py +357 -0
- spring/validation/exceptions.py +55 -0
- spring/validation/validator.py +139 -0
- spring/web/__init__.py +12 -0
- spring/web/actuator.py +319 -0
- spring/web/exception_handler.py +61 -0
- spring/web/health.py +399 -0
- spring/web/interceptor.py +91 -0
- spring/web/result.py +44 -0
- spring/web/swagger.py +601 -0
- spring/web/web_context.py +755 -0
- spring/websocket/__init__.py +86 -0
- spring/websocket/annotations.py +169 -0
- spring/websocket/broker.py +238 -0
- spring/websocket/exceptions.py +26 -0
- spring/websocket/handler.py +243 -0
- spring/websocket/router.py +526 -0
- spring/websocket/session.py +216 -0
- springbootai-1.8.0.dist-info/METADATA +2796 -0
- springbootai-1.8.0.dist-info/RECORD +175 -0
- springbootai-1.8.0.dist-info/WHEEL +5 -0
- springbootai-1.8.0.dist-info/entry_points.txt +2 -0
- springbootai-1.8.0.dist-info/licenses/LICENSE +7 -0
- springbootai-1.8.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AI 模块可观测性 - 复用框架 spring.monitoring.prometheus.PrometheusMetrics 单例,
|
|
3
|
+
记录 AI 调用次数、token 用量、延迟、错误率,对接企业 Prometheus + Grafana 监控体系。
|
|
4
|
+
"""
|
|
5
|
+
import logging
|
|
6
|
+
import time
|
|
7
|
+
from contextlib import contextmanager
|
|
8
|
+
from typing import Optional
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger("Spring.AI.Observability")
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
from spring.monitoring.prometheus import PrometheusMetrics
|
|
14
|
+
_PROMETHEUS_AVAILABLE = True
|
|
15
|
+
except ImportError:
|
|
16
|
+
_PROMETHEUS_AVAILABLE = False
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class AIMetrics:
|
|
20
|
+
"""
|
|
21
|
+
AI 指标采集器 - 单例,懒初始化 Prometheus 指标。
|
|
22
|
+
|
|
23
|
+
指标清单:
|
|
24
|
+
- ai_calls_total{provider,model,status} 调用次数(success/failure)
|
|
25
|
+
- ai_tokens_total{provider,type} token 用量(prompt/completion)
|
|
26
|
+
- ai_call_duration_seconds{provider,model} 调用延迟直方图
|
|
27
|
+
- ai_tool_calls_total{tool,status} 工具调用次数
|
|
28
|
+
- ai_circuit_breaker_state{provider} 熔断器状态(0=CLOSED 1=OPEN 2=HALF_OPEN)
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
_instance = None
|
|
32
|
+
|
|
33
|
+
def __new__(cls, *args, **kwargs):
|
|
34
|
+
if cls._instance is None:
|
|
35
|
+
cls._instance = super().__new__(cls)
|
|
36
|
+
return cls._instance
|
|
37
|
+
|
|
38
|
+
def __init__(self, enabled: bool = True):
|
|
39
|
+
if getattr(self, "_initialized", False):
|
|
40
|
+
return
|
|
41
|
+
self.enabled = enabled and _PROMETHEUS_AVAILABLE
|
|
42
|
+
self._metrics = None
|
|
43
|
+
if self.enabled:
|
|
44
|
+
try:
|
|
45
|
+
pm = PrometheusMetrics()
|
|
46
|
+
self._calls = pm.create_counter(
|
|
47
|
+
"ai_calls_total", "AI 模型调用次数",
|
|
48
|
+
labelnames=["provider", "model", "status"],
|
|
49
|
+
)
|
|
50
|
+
self._tokens = pm.create_counter(
|
|
51
|
+
"ai_tokens_total", "AI token 用量",
|
|
52
|
+
labelnames=["provider", "type"],
|
|
53
|
+
)
|
|
54
|
+
self._duration = pm.create_histogram(
|
|
55
|
+
"ai_call_duration_seconds", "AI 调用延迟(秒)",
|
|
56
|
+
labelnames=["provider", "model"],
|
|
57
|
+
buckets=[0.1, 0.5, 1, 2, 5, 10, 30, 60, 120],
|
|
58
|
+
)
|
|
59
|
+
self._tool_calls = pm.create_counter(
|
|
60
|
+
"ai_tool_calls_total", "AI 工具调用次数",
|
|
61
|
+
labelnames=["tool", "status"],
|
|
62
|
+
)
|
|
63
|
+
self._cb_state = pm.create_gauge(
|
|
64
|
+
"ai_circuit_breaker_state", "AI 熔断器状态(0=CLOSED,1=OPEN,2=HALF_OPEN)",
|
|
65
|
+
labelnames=["provider"],
|
|
66
|
+
)
|
|
67
|
+
self._metrics = pm
|
|
68
|
+
logger.info("AI Prometheus 指标已注册")
|
|
69
|
+
except Exception as exc:
|
|
70
|
+
logger.warning("AI 指标注册失败,降级为无监控: %s", exc)
|
|
71
|
+
self.enabled = False
|
|
72
|
+
self._initialized = True
|
|
73
|
+
|
|
74
|
+
def record_call(self, provider: str, model: str, status: str,
|
|
75
|
+
duration: float, usage: Optional[dict] = None):
|
|
76
|
+
"""记录一次模型调用"""
|
|
77
|
+
if not self.enabled:
|
|
78
|
+
return
|
|
79
|
+
try:
|
|
80
|
+
self._calls.labels(provider=provider, model=model,
|
|
81
|
+
status=status).inc()
|
|
82
|
+
self._duration.labels(provider=provider, model=model).observe(duration)
|
|
83
|
+
if usage:
|
|
84
|
+
if usage.get("prompt_tokens"):
|
|
85
|
+
self._tokens.labels(provider=provider,
|
|
86
|
+
type="prompt").inc(usage["prompt_tokens"])
|
|
87
|
+
if usage.get("completion_tokens"):
|
|
88
|
+
self._tokens.labels(provider=provider,
|
|
89
|
+
type="completion").inc(usage["completion_tokens"])
|
|
90
|
+
except Exception as exc: # 监控不应影响主流程
|
|
91
|
+
logger.debug("record_call 失败: %s", exc)
|
|
92
|
+
|
|
93
|
+
def record_tool_call(self, tool: str, status: str):
|
|
94
|
+
"""记录一次工具调用"""
|
|
95
|
+
if not self.enabled:
|
|
96
|
+
return
|
|
97
|
+
try:
|
|
98
|
+
self._tool_calls.labels(tool=tool, status=status).inc()
|
|
99
|
+
except Exception:
|
|
100
|
+
pass
|
|
101
|
+
|
|
102
|
+
def record_circuit_state(self, provider: str, state: str):
|
|
103
|
+
"""记录熔断器状态"""
|
|
104
|
+
if not self.enabled:
|
|
105
|
+
return
|
|
106
|
+
mapping = {"CLOSED": 0, "OPEN": 1, "HALF_OPEN": 2}
|
|
107
|
+
try:
|
|
108
|
+
self._cb_state.labels(provider=provider).set(mapping.get(state, 0))
|
|
109
|
+
except Exception:
|
|
110
|
+
pass
|
|
111
|
+
|
|
112
|
+
@contextmanager
|
|
113
|
+
def observe(self, provider: str, model: str):
|
|
114
|
+
"""上下文管理器:自动计时并记录成功/失败"""
|
|
115
|
+
start = time.time()
|
|
116
|
+
status = "success"
|
|
117
|
+
usage = None
|
|
118
|
+
try:
|
|
119
|
+
yield self
|
|
120
|
+
except Exception:
|
|
121
|
+
status = "failure"
|
|
122
|
+
raise
|
|
123
|
+
finally:
|
|
124
|
+
duration = time.time() - start
|
|
125
|
+
self.record_call(provider, model, status, duration, usage)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
# 全局单例
|
|
129
|
+
ai_metrics = AIMetrics()
|