cancan-microstack 0.0.1__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.
- cancan_microstack/__init__.py +14 -0
- cancan_microstack/__version__.py +10 -0
- cancan_microstack/assets/__init__.py +6 -0
- cancan_microstack/assets/builds/caddy/Caddyfile +187 -0
- cancan_microstack/assets/builds/caddy/DEPLOYMENT.md +303 -0
- cancan_microstack/assets/builds/caddy/Dockerfile +46 -0
- cancan_microstack/assets/builds/caddy/README.md +343 -0
- cancan_microstack/assets/builds/caddy/geoip/README.md +5 -0
- cancan_microstack/assets/builds/caddy/start.sh +78 -0
- cancan_microstack/assets/builds/caddy/waf/coraza.conf +179 -0
- cancan_microstack/assets/builds/service/Dockerfile +59 -0
- cancan_microstack/assets/builds/service/README.md +13 -0
- cancan_microstack/assets/ddl/create_db.sql +22 -0
- cancan_microstack/assets/ddl/infra/execution_log_tbl.sql +46 -0
- cancan_microstack/assets/ddl/infra/node_instance_tbl.sql +56 -0
- cancan_microstack/assets/ddl/infra/service_action_log_tbl.sql +36 -0
- cancan_microstack/assets/ddl/infra/service_config_tbl.sql +26 -0
- cancan_microstack/assets/ddl/infra/service_info_tbl.sql +45 -0
- cancan_microstack/assets/ddl/infra/service_instance_tbl.sql +54 -0
- cancan_microstack/assets/ddl/infra/service_operation_tbl.sql +47 -0
- cancan_microstack/assets/ddl/infra/workflow_definition_tbl.sql +60 -0
- cancan_microstack/assets/ddl/infra/workflow_definition_version_tbl.sql +35 -0
- cancan_microstack/assets/ddl/infra/workflow_engine_alert_tbl.sql +34 -0
- cancan_microstack/assets/ddl/infra/workflow_run_tbl.sql +52 -0
- cancan_microstack/assets/ddl/ops/admin_user_tbl.sql +34 -0
- cancan_microstack/assets/ddl/ops/caddy_access_log_tbl.sql +91 -0
- cancan_microstack/assets/ddl/ops/caddy_certificate_tbl.sql +59 -0
- cancan_microstack/assets/ddl/ops/caddy_rate_limit_tbl.sql +64 -0
- cancan_microstack/assets/ddl/ops/caddy_route_tbl.sql +63 -0
- cancan_microstack/assets/ddl/ops/caddy_stats_tbl.sql +77 -0
- cancan_microstack/assets/ddl/trigger.sql +21 -0
- cancan_microstack/assets/docker/docker-compose.infra.yml +401 -0
- cancan_microstack/assets/scripts/README.md +195 -0
- cancan_microstack/assets/scripts/docker/build_images.sh +44 -0
- cancan_microstack/assets/scripts/docker/force_rebuild_images.sh +38 -0
- cancan_microstack/assets/scripts/docker/rebuild_all.sh +34 -0
- cancan_microstack/assets/scripts/docker/rebuild_compose.sh +61 -0
- cancan_microstack/assets/scripts/docker/restart.sh +35 -0
- cancan_microstack/assets/scripts/docker/restart_compose.sh +35 -0
- cancan_microstack/assets/scripts/docker/start.sh +78 -0
- cancan_microstack/assets/scripts/docker/start_all.sh +46 -0
- cancan_microstack/assets/scripts/docker/start_compose.sh +66 -0
- cancan_microstack/assets/scripts/docker/stop.sh +67 -0
- cancan_microstack/assets/scripts/docker/stop_all.sh +38 -0
- cancan_microstack/assets/scripts/docker/stop_compose.sh +38 -0
- cancan_microstack/assets/scripts/podman/build_images_podman.sh +59 -0
- cancan_microstack/assets/scripts/podman/cleanup_podman.sh +25 -0
- cancan_microstack/assets/scripts/podman/force_rebuild_images_podman.sh +56 -0
- cancan_microstack/assets/scripts/podman/rebuild_all_podman.sh +37 -0
- cancan_microstack/assets/scripts/podman/rebuild_compose_podman.sh +60 -0
- cancan_microstack/assets/scripts/podman/restart_compose_podman.sh +73 -0
- cancan_microstack/assets/scripts/podman/start_all_podman.sh +66 -0
- cancan_microstack/assets/scripts/podman/start_compose_podman.sh +80 -0
- cancan_microstack/assets/scripts/podman/start_podman.sh +91 -0
- cancan_microstack/assets/scripts/podman/stop.sh +73 -0
- cancan_microstack/assets/scripts/podman/stop_all_podman.sh +34 -0
- cancan_microstack/assets/scripts/podman/stop_compose_podman.sh +58 -0
- cancan_microstack/assets/scripts/start_controllersrv.sh +9 -0
- cancan_microstack/assets/scripts/utils/check_all_db_tables.sh +104 -0
- cancan_microstack/assets/scripts/utils/check_env.sh +177 -0
- cancan_microstack/assets/scripts/utils/check_service_management_deployment.sh +225 -0
- cancan_microstack/assets/scripts/utils/deploy_service_management.sh +176 -0
- cancan_microstack/assets/scripts/utils/force_reload_infrasrv.sh +52 -0
- cancan_microstack/assets/scripts/utils/monitor_service_management.sh +187 -0
- cancan_microstack/assets/scripts/utils/reset_postgres_volume.sh +68 -0
- cancan_microstack/assets/scripts/utils/test_async_operations.sh +141 -0
- cancan_microstack/assets/scripts/utils/verify_real_operations.sh +76 -0
- cancan_microstack/assets/service/Dockerfile +65 -0
- cancan_microstack/assets/www/adminops/assets/AppEmpty.vue_vue_type_script_setup_true_lang-BOKUurnM.js +1 -0
- cancan_microstack/assets/www/adminops/assets/ConfigManage-DKV5YOUz.js +1 -0
- cancan_microstack/assets/www/adminops/assets/ConfigManage-Y5bhy7wG.css +1 -0
- cancan_microstack/assets/www/adminops/assets/ConsoleManage-8ljYvCW2.js +1 -0
- cancan_microstack/assets/www/adminops/assets/ConsoleManage-BWpyqbuQ.css +1 -0
- cancan_microstack/assets/www/adminops/assets/DashboardNew-B9Nf1OPl.js +1 -0
- cancan_microstack/assets/www/adminops/assets/DashboardNew-DYWZKQ1V.css +1 -0
- cancan_microstack/assets/www/adminops/assets/LogSearch-CA0Jhe78.js +1 -0
- cancan_microstack/assets/www/adminops/assets/LogSearch-CCZfTNPF.css +1 -0
- cancan_microstack/assets/www/adminops/assets/LoginView-BId3kP3M.css +1 -0
- cancan_microstack/assets/www/adminops/assets/LoginView-BQZTV_Qy.js +1 -0
- cancan_microstack/assets/www/adminops/assets/OperationProgressDialog-BdEYwqFq.js +1 -0
- cancan_microstack/assets/www/adminops/assets/OperationProgressDialog-D-pASR8G.css +1 -0
- cancan_microstack/assets/www/adminops/assets/PageContainer-Byss-yUC.js +1 -0
- cancan_microstack/assets/www/adminops/assets/PageContainer-C3nSZwM7.css +1 -0
- cancan_microstack/assets/www/adminops/assets/RateLimitManage-BDI8jLpC.css +1 -0
- cancan_microstack/assets/www/adminops/assets/RateLimitManage-DJY4NiF-.js +1 -0
- cancan_microstack/assets/www/adminops/assets/RouteManage-DaUQ4QLw.css +1 -0
- cancan_microstack/assets/www/adminops/assets/RouteManage-w9XCU0UA.js +1 -0
- cancan_microstack/assets/www/adminops/assets/ServiceCard-BFzHe6Tw.css +1 -0
- cancan_microstack/assets/www/adminops/assets/ServiceCard-BJUhWnA-.js +1 -0
- cancan_microstack/assets/www/adminops/assets/ServiceDetail-Cw24WuKp.js +1 -0
- cancan_microstack/assets/www/adminops/assets/ServiceDetail-Yum47zdB.css +1 -0
- cancan_microstack/assets/www/adminops/assets/ServiceList-C7ryvbhE.js +1 -0
- cancan_microstack/assets/www/adminops/assets/ServiceList-Cgd01fUx.css +1 -0
- cancan_microstack/assets/www/adminops/assets/ServiceLogs-COpG9H0h.js +1 -0
- cancan_microstack/assets/www/adminops/assets/ServiceLogs-H_Alq0cf.css +1 -0
- cancan_microstack/assets/www/adminops/assets/StatsOverview-D0TwMQkA.js +39 -0
- cancan_microstack/assets/www/adminops/assets/StatsOverview-lqAN6pqM.css +1 -0
- cancan_microstack/assets/www/adminops/assets/TotpBindView-CWlAmzFt.js +1 -0
- cancan_microstack/assets/www/adminops/assets/TotpBindView-HoQC1lhx.css +1 -0
- cancan_microstack/assets/www/adminops/assets/TotpVerifyView-BHN1VtX1.css +1 -0
- cancan_microstack/assets/www/adminops/assets/TotpVerifyView-D3w_lZk8.js +1 -0
- cancan_microstack/assets/www/adminops/assets/WorkflowCenter-DU_mpIA0.css +1 -0
- cancan_microstack/assets/www/adminops/assets/WorkflowCenter-i50rZyxN.js +1 -0
- cancan_microstack/assets/www/adminops/assets/WorkflowDesigner-CnHokPL9.js +1 -0
- cancan_microstack/assets/www/adminops/assets/WorkflowDesigner-DaZaZpLd.css +1 -0
- cancan_microstack/assets/www/adminops/assets/WorkflowRuns-B09hK48c.js +1 -0
- cancan_microstack/assets/www/adminops/assets/WorkflowRuns-wGutKIIU.css +1 -0
- cancan_microstack/assets/www/adminops/assets/caddy-nnCKf8fG.js +1 -0
- cancan_microstack/assets/www/adminops/assets/format-Cuzxgna9.js +1 -0
- cancan_microstack/assets/www/adminops/assets/index-CiFlm8oc.js +64 -0
- cancan_microstack/assets/www/adminops/assets/index-UW0T1Dkc.css +1 -0
- cancan_microstack/assets/www/adminops/assets/service-BYlgGPs_.js +1 -0
- cancan_microstack/assets/www/adminops/assets/service-operation-6GzLw2Z1.js +1 -0
- cancan_microstack/assets/www/adminops/assets/style-CcIXnQ5y.css +1 -0
- cancan_microstack/assets/www/adminops/assets/style-lRnStdGu.js +39 -0
- cancan_microstack/assets/www/adminops/assets/useDebounce-BRlqfXqf.js +1 -0
- cancan_microstack/assets/www/adminops/assets/workflow-CUXs39Ac.js +1 -0
- cancan_microstack/assets/www/adminops/index.html +16 -0
- cancan_microstack/assets/www/adminops/vite.svg +1 -0
- cancan_microstack/cli/__init__.py +14 -0
- cancan_microstack/cli/__main__.py +9 -0
- cancan_microstack/cli/main.py +552 -0
- cancan_microstack/cmd/__init__.py +54 -0
- cancan_microstack/cmd/cancan/__init__.py +12 -0
- cancan_microstack/cmd/cancan/run.py +395 -0
- cancan_microstack/cmd/controllersrv/__init__.py +0 -0
- cancan_microstack/cmd/controllersrv/run.py +131 -0
- cancan_microstack/cmd/infrasrv/__init__.py +5 -0
- cancan_microstack/cmd/infrasrv/run.py +100 -0
- cancan_microstack/cmd/opsbffsrv/__init__.py +5 -0
- cancan_microstack/cmd/opsbffsrv/run.py +96 -0
- cancan_microstack/core/__init__.py +5 -0
- cancan_microstack/core/assets.py +123 -0
- cancan_microstack/core/compose_builder.py +102 -0
- cancan_microstack/core/doctor.py +152 -0
- cancan_microstack/core/microstack.py +71 -0
- cancan_microstack/core/runner.py +56 -0
- cancan_microstack/core/stack_manager.py +186 -0
- cancan_microstack/public/__init__.py +7 -0
- cancan_microstack/public/api/__init__.py +1 -0
- cancan_microstack/public/api/controllersrv_client.py +277 -0
- cancan_microstack/public/api/infrasrv_client.py +404 -0
- cancan_microstack/public/const/__init__.py +1 -0
- cancan_microstack/public/const/action_consts.py +18 -0
- cancan_microstack/public/const/app_consts.py +42 -0
- cancan_microstack/public/const/caddy_consts.py +22 -0
- cancan_microstack/public/const/controllersrv_consts.py +163 -0
- cancan_microstack/public/const/docker_consts.py +15 -0
- cancan_microstack/public/const/error.py +56 -0
- cancan_microstack/public/const/health_consts.py +52 -0
- cancan_microstack/public/const/hook_enums.py +56 -0
- cancan_microstack/public/const/logging_enums.py +13 -0
- cancan_microstack/public/const/metrics_enums.py +36 -0
- cancan_microstack/public/const/monitor_enums.py +26 -0
- cancan_microstack/public/const/operation_consts.py +53 -0
- cancan_microstack/public/const/opsbffsrv_error.py +92 -0
- cancan_microstack/public/const/overrides_consts.py +13 -0
- cancan_microstack/public/const/redis.py +17 -0
- cancan_microstack/public/const/service_consts.py +15 -0
- cancan_microstack/public/const/workflow_consts.py +65 -0
- cancan_microstack/public/error.py +41 -0
- cancan_microstack/public/logging/__init__.py +0 -0
- cancan_microstack/public/logging/initializer.py +109 -0
- cancan_microstack/public/logging/mq_handler.py +279 -0
- cancan_microstack/public/schemas/__init__.py +1 -0
- cancan_microstack/public/schemas/caddy/__init__.py +381 -0
- cancan_microstack/public/schemas/caddy/analysis.py +90 -0
- cancan_microstack/public/schemas/caddy/route.py +18 -0
- cancan_microstack/public/schemas/common.py +79 -0
- cancan_microstack/public/schemas/controllersrv/__init__.py +3 -0
- cancan_microstack/public/schemas/controllersrv/async_requests.py +30 -0
- cancan_microstack/public/schemas/controllersrv/compose_models.py +47 -0
- cancan_microstack/public/schemas/controllersrv/const.py +24 -0
- cancan_microstack/public/schemas/controllersrv/docker_models.py +45 -0
- cancan_microstack/public/schemas/controllersrv/docker_responses.py +104 -0
- cancan_microstack/public/schemas/controllersrv/requests.py +54 -0
- cancan_microstack/public/schemas/controllersrv/responses.py +124 -0
- cancan_microstack/public/schemas/controllersrv/task_models.py +102 -0
- cancan_microstack/public/schemas/controllersrv/validation.py +23 -0
- cancan_microstack/public/schemas/hook_metrics.py +124 -0
- cancan_microstack/public/schemas/hooks.py +39 -0
- cancan_microstack/public/schemas/infra/__init__.py +0 -0
- cancan_microstack/public/schemas/infra/cleanup.py +25 -0
- cancan_microstack/public/schemas/infra/container.py +74 -0
- cancan_microstack/public/schemas/infra/enums.py +135 -0
- cancan_microstack/public/schemas/infra/health_check.py +42 -0
- cancan_microstack/public/schemas/infra/hook_log.py +42 -0
- cancan_microstack/public/schemas/infra/operation.py +90 -0
- cancan_microstack/public/schemas/infra/overview.py +25 -0
- cancan_microstack/public/schemas/infra/push.py +33 -0
- cancan_microstack/public/schemas/infra/service_action_log.py +47 -0
- cancan_microstack/public/schemas/infra/service_config.py +10 -0
- cancan_microstack/public/schemas/infra/service_info.py +69 -0
- cancan_microstack/public/schemas/infra/service_instance.py +93 -0
- cancan_microstack/public/schemas/infra/service_management.py +152 -0
- cancan_microstack/public/schemas/infra/service_operation.py +79 -0
- cancan_microstack/public/schemas/infra/service_registry.py +158 -0
- cancan_microstack/public/schemas/infra/status_types.py +19 -0
- cancan_microstack/public/schemas/infra/workflow.py +566 -0
- cancan_microstack/public/schemas/logging/__init__.py +1 -0
- cancan_microstack/public/schemas/logging/log_event.py +121 -0
- cancan_microstack/public/schemas/opsbffsrv/__init__.py +1 -0
- cancan_microstack/public/schemas/opsbffsrv/async_ops.py +17 -0
- cancan_microstack/public/schemas/opsbffsrv/db_admin.py +147 -0
- cancan_microstack/public/schemas/opsbffsrv/db_init.py +48 -0
- cancan_microstack/public/schemas/opsbffsrv/service_config.py +89 -0
- cancan_microstack/public/schemas/opsbffsrv/service_logs.py +54 -0
- cancan_microstack/public/schemas/service_operation.py +24 -0
- cancan_microstack/public/schemas/service_registry.py +40 -0
- cancan_microstack/public/types/__init__.py +7 -0
- cancan_microstack/public/web/__init__.py +0 -0
- cancan_microstack/public/web/config_value.py +105 -0
- cancan_microstack/public/web/server.py +385 -0
- cancan_microstack/py.typed +0 -0
- cancan_microstack/runtime/__init__.py +0 -0
- cancan_microstack/runtime/compose_cmd.py +228 -0
- cancan_microstack/runtime/host_daemon.py +318 -0
- cancan_microstack/runtime/overrides.py +103 -0
- cancan_microstack/runtime/resources.py +25 -0
- cancan_microstack/runtime/workspace.py +94 -0
- cancan_microstack/services/__init__.py +0 -0
- cancan_microstack/services/controllersrv/__init__.py +8 -0
- cancan_microstack/services/controllersrv/application/__init__.py +0 -0
- cancan_microstack/services/controllersrv/application/docker_compose_app.py +427 -0
- cancan_microstack/services/controllersrv/conf/__init__.py +0 -0
- cancan_microstack/services/controllersrv/conf/config.py +76 -0
- cancan_microstack/services/controllersrv/conf/settings.py +54 -0
- cancan_microstack/services/controllersrv/domain/__init__.py +0 -0
- cancan_microstack/services/controllersrv/domain/docker_compose/__init__.py +0 -0
- cancan_microstack/services/controllersrv/domain/docker_compose/docker_compose_domain.py +278 -0
- cancan_microstack/services/controllersrv/domain/service_validator.py +327 -0
- cancan_microstack/services/controllersrv/domain/task/__init__.py +17 -0
- cancan_microstack/services/controllersrv/domain/task/task_queue.py +286 -0
- cancan_microstack/services/controllersrv/domain/task/task_worker.py +495 -0
- cancan_microstack/services/controllersrv/infrastructure/__init__.py +0 -0
- cancan_microstack/services/controllersrv/interface/__init__.py +0 -0
- cancan_microstack/services/controllersrv/interface/api/__init__.py +0 -0
- cancan_microstack/services/controllersrv/interface/api/docker_control_api.py +470 -0
- cancan_microstack/services/controllersrv/router.py +132 -0
- cancan_microstack/services/infrasrv/__init__.py +4 -0
- cancan_microstack/services/infrasrv/application/__init__.py +0 -0
- cancan_microstack/services/infrasrv/application/health_check_app.py +24 -0
- cancan_microstack/services/infrasrv/application/logging/__init__.py +1 -0
- cancan_microstack/services/infrasrv/application/logging/log_ingestion_service.py +183 -0
- cancan_microstack/services/infrasrv/application/service_config.py +22 -0
- cancan_microstack/services/infrasrv/application/service_logs_app.py +53 -0
- cancan_microstack/services/infrasrv/application/service_management_app.py +689 -0
- cancan_microstack/services/infrasrv/application/service_operation_tracker.py +251 -0
- cancan_microstack/services/infrasrv/application/service_registry.py +53 -0
- cancan_microstack/services/infrasrv/application/workflow/__init__.py +0 -0
- cancan_microstack/services/infrasrv/application/workflow/workflow_app.py +991 -0
- cancan_microstack/services/infrasrv/application/workflow/workflow_queue.py +302 -0
- cancan_microstack/services/infrasrv/application/workflow/workflow_tasks.py +46 -0
- cancan_microstack/services/infrasrv/application/workflow/workflow_worker_runtime.py +122 -0
- cancan_microstack/services/infrasrv/conf/__init__.py +0 -0
- cancan_microstack/services/infrasrv/conf/config.py +98 -0
- cancan_microstack/services/infrasrv/domain/__init__.py +0 -0
- cancan_microstack/services/infrasrv/domain/health_check/__init__.py +3 -0
- cancan_microstack/services/infrasrv/domain/health_check/health_check_domain.py +576 -0
- cancan_microstack/services/infrasrv/domain/hooks/__init__.py +19 -0
- cancan_microstack/services/infrasrv/domain/hooks/builtin_hooks.py +308 -0
- cancan_microstack/services/infrasrv/domain/hooks/hook_registry.py +43 -0
- cancan_microstack/services/infrasrv/domain/hooks/hooks_log_utils.py +275 -0
- cancan_microstack/services/infrasrv/domain/hooks/init.py +17 -0
- cancan_microstack/services/infrasrv/domain/hooks/metrics.py +205 -0
- cancan_microstack/services/infrasrv/domain/hooks/pre_registration_hooks.py +490 -0
- cancan_microstack/services/infrasrv/domain/registry/__init__.py +0 -0
- cancan_microstack/services/infrasrv/domain/registry/service_registry.py +509 -0
- cancan_microstack/services/infrasrv/domain/service_config/__init__.py +0 -0
- cancan_microstack/services/infrasrv/domain/service_config/service_config.py +50 -0
- cancan_microstack/services/infrasrv/domain/service_logs/__init__.py +0 -0
- cancan_microstack/services/infrasrv/domain/service_logs/service_logs_domain.py +51 -0
- cancan_microstack/services/infrasrv/domain/workflow/__init__.py +4 -0
- cancan_microstack/services/infrasrv/domain/workflow/engine.py +159 -0
- cancan_microstack/services/infrasrv/domain/workflow/node_handlers.py +509 -0
- cancan_microstack/services/infrasrv/domain/workflow/workflow_domain.py +164 -0
- cancan_microstack/services/infrasrv/infrastructure/__init__.py +0 -0
- cancan_microstack/services/infrasrv/infrastructure/api/__init__.py +0 -0
- cancan_microstack/services/infrasrv/infrastructure/api/controllersrv_api.py +165 -0
- cancan_microstack/services/infrasrv/infrastructure/cache/__init__.py +0 -0
- cancan_microstack/services/infrasrv/infrastructure/cache/service_registry_cache.py +174 -0
- cancan_microstack/services/infrasrv/infrastructure/db/__init__.py +0 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/__init__.py +0 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/execution_log_tbl.py +53 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/node_instance_tbl.py +55 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/service_action_log_tbl.py +44 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/service_config_tbl.py +30 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/service_info_tbl.py +59 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/service_instance_tbl.py +88 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/service_operation_tbl.py +73 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/workflow_definition_tbl.py +55 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/workflow_definition_version_tbl.py +43 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/workflow_engine_alert_tbl.py +57 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/workflow_run_tbl.py +56 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/__init__.py +0 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/service_action_log_op.py +239 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/service_config.py +80 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/service_config_manager.py +198 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/service_info_op.py +297 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/service_instance_op.py +688 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/service_operation_op.py +387 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/service_registry.py +124 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/workflow_op.py +804 -0
- cancan_microstack/services/infrasrv/infrastructure/ddl_manager.py +31 -0
- cancan_microstack/services/infrasrv/infrastructure/mongo/__init__.py +1 -0
- cancan_microstack/services/infrasrv/infrastructure/mongo/log_repository.py +129 -0
- cancan_microstack/services/infrasrv/interface/__init__.py +0 -0
- cancan_microstack/services/infrasrv/interface/api/__init__.py +0 -0
- cancan_microstack/services/infrasrv/interface/api/health_check_api.py +29 -0
- cancan_microstack/services/infrasrv/interface/api/hooks.py +284 -0
- cancan_microstack/services/infrasrv/interface/api/internal.py +49 -0
- cancan_microstack/services/infrasrv/interface/api/internal_instance_api.py +265 -0
- cancan_microstack/services/infrasrv/interface/api/internal_operation_api.py +206 -0
- cancan_microstack/services/infrasrv/interface/api/service_config.py +50 -0
- cancan_microstack/services/infrasrv/interface/api/service_logs_api.py +49 -0
- cancan_microstack/services/infrasrv/interface/api/service_management_api.py +113 -0
- cancan_microstack/services/infrasrv/interface/api/service_registry.py +117 -0
- cancan_microstack/services/infrasrv/interface/api/workflow_api.py +303 -0
- cancan_microstack/services/infrasrv/interface/schedule/__init__.py +0 -0
- cancan_microstack/services/infrasrv/interface/schedule/cleanup.py +13 -0
- cancan_microstack/services/infrasrv/interface/schedule/health_check.py +27 -0
- cancan_microstack/services/infrasrv/interface/schedule/log_cleanup.py +26 -0
- cancan_microstack/services/infrasrv/interface/schedule/operation_tracker.py +25 -0
- cancan_microstack/services/infrasrv/interface/schedule/scheduler.py +39 -0
- cancan_microstack/services/infrasrv/interface/schedule/workflow_scheduler.py +115 -0
- cancan_microstack/services/infrasrv/router.py +341 -0
- cancan_microstack/services/opsbffsrv/__init__.py +4 -0
- cancan_microstack/services/opsbffsrv/application/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/application/async_operation_app.py +150 -0
- cancan_microstack/services/opsbffsrv/application/auth_app.py +285 -0
- cancan_microstack/services/opsbffsrv/application/caddy/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/application/caddy/access_log_analysis_app.py +344 -0
- cancan_microstack/services/opsbffsrv/application/caddy/access_log_ingestion_service.py +169 -0
- cancan_microstack/services/opsbffsrv/application/caddy/certificate_management_app.py +355 -0
- cancan_microstack/services/opsbffsrv/application/caddy/rate_limit_management_app.py +496 -0
- cancan_microstack/services/opsbffsrv/application/caddy/route_management_app.py +401 -0
- cancan_microstack/services/opsbffsrv/application/caddy/stats_aggregation_app.py +364 -0
- cancan_microstack/services/opsbffsrv/application/db_admin_app.py +103 -0
- cancan_microstack/services/opsbffsrv/application/db_init_app.py +283 -0
- cancan_microstack/services/opsbffsrv/application/logging/__init__.py +1 -0
- cancan_microstack/services/opsbffsrv/application/logging/log_query_app.py +28 -0
- cancan_microstack/services/opsbffsrv/application/service_config.py +158 -0
- cancan_microstack/services/opsbffsrv/application/service_logs_app.py +74 -0
- cancan_microstack/services/opsbffsrv/application/service_registry.py +36 -0
- cancan_microstack/services/opsbffsrv/application/workflow_ops_app.py +730 -0
- cancan_microstack/services/opsbffsrv/conf/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/conf/config.py +224 -0
- cancan_microstack/services/opsbffsrv/domain/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/domain/auth/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/domain/auth/admin_init.py +38 -0
- cancan_microstack/services/opsbffsrv/domain/auth/auth_domain.py +108 -0
- cancan_microstack/services/opsbffsrv/domain/caddy/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/domain/caddy/access_log_analysis.py +358 -0
- cancan_microstack/services/opsbffsrv/domain/caddy/certificate_management.py +325 -0
- cancan_microstack/services/opsbffsrv/domain/caddy/default_routes.py +53 -0
- cancan_microstack/services/opsbffsrv/domain/caddy/rate_limit_management.py +308 -0
- cancan_microstack/services/opsbffsrv/domain/caddy/route_management.py +279 -0
- cancan_microstack/services/opsbffsrv/domain/caddy/stats_aggregation.py +654 -0
- cancan_microstack/services/opsbffsrv/domain/db_admin/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/domain/db_admin/db_admin_domain.py +118 -0
- cancan_microstack/services/opsbffsrv/domain/db_init/__init__.py +3 -0
- cancan_microstack/services/opsbffsrv/domain/db_init/db_init_domain.py +358 -0
- cancan_microstack/services/opsbffsrv/domain/logging/__init__.py +1 -0
- cancan_microstack/services/opsbffsrv/domain/logging/log_query_domain.py +99 -0
- cancan_microstack/services/opsbffsrv/domain/service_config/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/domain/service_config/service_config.py +81 -0
- cancan_microstack/services/opsbffsrv/domain/service_registry/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/domain/service_registry/service_registry.py +292 -0
- cancan_microstack/services/opsbffsrv/infrastructure/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/infrastructure/api/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/infrastructure/api/infrasrv_api.py +242 -0
- cancan_microstack/services/opsbffsrv/infrastructure/auth/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/infrastructure/auth/captcha_service.py +67 -0
- cancan_microstack/services/opsbffsrv/infrastructure/auth/password_service.py +12 -0
- cancan_microstack/services/opsbffsrv/infrastructure/auth/redis_store.py +131 -0
- cancan_microstack/services/opsbffsrv/infrastructure/auth/totp_service.py +59 -0
- cancan_microstack/services/opsbffsrv/infrastructure/caddy/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/infrastructure/caddy/access_log_parser.py +307 -0
- cancan_microstack/services/opsbffsrv/infrastructure/caddy/admin_api_client.py +678 -0
- cancan_microstack/services/opsbffsrv/infrastructure/caddy/ip_geo_locator.py +176 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/admin_user_tbl.py +33 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/caddy_access_log_tbl.py +90 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/caddy_certificate_tbl.py +65 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/caddy_rate_limit_tbl.py +69 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/caddy_route_tbl.py +66 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/caddy_stats_tbl.py +78 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/service_action_log_tbl.py +44 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/service_config_tbl.py +30 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/service_info_tbl.py +51 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/service_instance_tbl.py +68 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/admin_user_operate.py +59 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/caddy_access_log.py +531 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/caddy_certificate.py +451 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/caddy_rate_limit.py +360 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/caddy_route.py +271 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/caddy_stats.py +343 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/service_action_log_op.py +57 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/service_config.py +86 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/service_info_op.py +79 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/service_instance.py +58 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/service_registry.py +138 -0
- cancan_microstack/services/opsbffsrv/infrastructure/ddl_manager.py +31 -0
- cancan_microstack/services/opsbffsrv/infrastructure/mongo/__init__.py +1 -0
- cancan_microstack/services/opsbffsrv/infrastructure/mongo/log_query_repository.py +87 -0
- cancan_microstack/services/opsbffsrv/interface/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/interface/api/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/interface/api/async_operation_api.py +137 -0
- cancan_microstack/services/opsbffsrv/interface/api/auth_api.py +113 -0
- cancan_microstack/services/opsbffsrv/interface/api/caddy/__init__.py +3 -0
- cancan_microstack/services/opsbffsrv/interface/api/caddy/access_log_api.py +174 -0
- cancan_microstack/services/opsbffsrv/interface/api/caddy/certificate_api.py +235 -0
- cancan_microstack/services/opsbffsrv/interface/api/caddy/rate_limit_api.py +302 -0
- cancan_microstack/services/opsbffsrv/interface/api/caddy/route_api.py +250 -0
- cancan_microstack/services/opsbffsrv/interface/api/caddy/stats_api.py +243 -0
- cancan_microstack/services/opsbffsrv/interface/api/db_admin_api.py +62 -0
- cancan_microstack/services/opsbffsrv/interface/api/db_init_api.py +109 -0
- cancan_microstack/services/opsbffsrv/interface/api/instance_management_api.py +165 -0
- cancan_microstack/services/opsbffsrv/interface/api/log_query_api.py +41 -0
- cancan_microstack/services/opsbffsrv/interface/api/mongo_express_proxy_api.py +181 -0
- cancan_microstack/services/opsbffsrv/interface/api/pgweb_proxy_api.py +154 -0
- cancan_microstack/services/opsbffsrv/interface/api/rabbitmq_mgmt_proxy_api.py +518 -0
- cancan_microstack/services/opsbffsrv/interface/api/redis_commander_proxy_api.py +133 -0
- cancan_microstack/services/opsbffsrv/interface/api/service_config.py +146 -0
- cancan_microstack/services/opsbffsrv/interface/api/service_logs_api.py +81 -0
- cancan_microstack/services/opsbffsrv/interface/api/service_registry.py +66 -0
- cancan_microstack/services/opsbffsrv/interface/api/workflow_ops_api.py +413 -0
- cancan_microstack/services/opsbffsrv/interface/middleware/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/interface/middleware/auth_middleware.py +52 -0
- cancan_microstack/services/opsbffsrv/router.py +901 -0
- cancan_microstack/utils/__init__.py +1 -0
- cancan_microstack/utils/container_env.py +218 -0
- cancan_microstack-0.0.1.dist-info/METADATA +155 -0
- cancan_microstack-0.0.1.dist-info/RECORD +440 -0
- cancan_microstack-0.0.1.dist-info/WHEEL +5 -0
- cancan_microstack-0.0.1.dist-info/entry_points.txt +2 -0
- cancan_microstack-0.0.1.dist-info/licenses/LICENSE +21 -0
- cancan_microstack-0.0.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
"""
|
|
2
|
+
本模块提供了一个可重用的日志处理器,用于将日志记录发布到 RabbitMQ 交换机。
|
|
3
|
+
This module provides a reusable logging handler for publishing log records to a RabbitMQ exchange.
|
|
4
|
+
"""
|
|
5
|
+
import asyncio
|
|
6
|
+
import logging
|
|
7
|
+
import os
|
|
8
|
+
import socket
|
|
9
|
+
import threading
|
|
10
|
+
from concurrent.futures import Future
|
|
11
|
+
from datetime import (
|
|
12
|
+
datetime,
|
|
13
|
+
timezone,
|
|
14
|
+
)
|
|
15
|
+
from typing import (
|
|
16
|
+
Any,
|
|
17
|
+
Dict,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
import aio_pika
|
|
21
|
+
import orjson
|
|
22
|
+
from aio_pika import (
|
|
23
|
+
DeliveryMode,
|
|
24
|
+
ExchangeType,
|
|
25
|
+
Message,
|
|
26
|
+
RobustConnection,
|
|
27
|
+
)
|
|
28
|
+
from nanoid import generate
|
|
29
|
+
|
|
30
|
+
from cancan_microstack.public.const.app_consts import LogLevelEnum
|
|
31
|
+
from cancan_microstack.public.schemas.logging.log_event import LogEventCreate
|
|
32
|
+
from linglong_web.utils import get_request_id
|
|
33
|
+
from linglong_web.utils import logger as app_logger
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def build_log_routing_key(template: str, service_name: str, level: LogLevelEnum) -> str:
|
|
37
|
+
"""构建日志路由键 / Build log routing key."""
|
|
38
|
+
try:
|
|
39
|
+
return template.format(service=service_name, level=level.value.lower())
|
|
40
|
+
except KeyError:
|
|
41
|
+
return f"logs.business.{service_name}.{level.value.lower()}"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class RabbitMQHandler(logging.Handler):
|
|
45
|
+
"""
|
|
46
|
+
一个将日志记录异步发布到 RabbitMQ 交换机 (Exchange) 的日志处理器。
|
|
47
|
+
它的设计是线程安全的,旨在连接同步日志框架与异步 RabbitMQ 客户端 (`aio_pika`)。
|
|
48
|
+
|
|
49
|
+
A logging handler that asynchronously publishes log records to a RabbitMQ exchange.
|
|
50
|
+
It is designed to be thread-safe and to bridge the synchronous logging framework
|
|
51
|
+
with an asynchronous RabbitMQ client (`aio_pika`).
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
def __init__(
|
|
55
|
+
self,
|
|
56
|
+
*,
|
|
57
|
+
connection: RobustConnection,
|
|
58
|
+
service_name: str,
|
|
59
|
+
exchange_name: str,
|
|
60
|
+
routing_template: str = "log.{service}.{level}",
|
|
61
|
+
instance_id: str | None = None,
|
|
62
|
+
loop: asyncio.AbstractEventLoop | None = None,
|
|
63
|
+
):
|
|
64
|
+
"""
|
|
65
|
+
初始化处理器。
|
|
66
|
+
Initializes the handler.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
connection: 一个 aio_pika 的 RobustConnection 实例。/ An instance of aio_pika's RobustConnection.
|
|
70
|
+
service_name: 当前服务的名称。/ Name of the current service.
|
|
71
|
+
exchange_name: 要发布到的 RabbitMQ 交换机名称。/ Name of the RabbitMQ exchange to publish to.
|
|
72
|
+
instance_id: 服务实例的唯一标识符。如果未提供,将自动生成。/ A unique identifier for the service instance. Auto-generated if not provided.
|
|
73
|
+
loop: 运行 aio_pika 的事件循环。如果未提供,将获取当前正在运行的循环。/ The event loop running aio_pika. Gets the current running loop if not provided.
|
|
74
|
+
"""
|
|
75
|
+
super().__init__()
|
|
76
|
+
self._connection = connection
|
|
77
|
+
self._service_name = service_name
|
|
78
|
+
self._exchange_name = exchange_name
|
|
79
|
+
self._routing_template = routing_template
|
|
80
|
+
self._instance_id = instance_id or generate(size=12)
|
|
81
|
+
self._loop = loop or asyncio.get_running_loop()
|
|
82
|
+
|
|
83
|
+
self._channel: aio_pika.RobustChannel | None = None
|
|
84
|
+
self._exchange: aio_pika.Exchange | None = None
|
|
85
|
+
|
|
86
|
+
self._host = os.environ.get("HOSTNAME") or socket.gethostname()
|
|
87
|
+
self._cached_ip: str | None = None
|
|
88
|
+
|
|
89
|
+
self._pending_futures: set[Future] = set()
|
|
90
|
+
self._pending_lock = threading.Lock()
|
|
91
|
+
|
|
92
|
+
# 在事件循环中初始化 Channel 和 Exchange
|
|
93
|
+
# Initialize channel and exchange in the event loop
|
|
94
|
+
asyncio.run_coroutine_threadsafe(self._initialize_mq_objects(), self._loop)
|
|
95
|
+
|
|
96
|
+
async def _initialize_mq_objects(self):
|
|
97
|
+
"""
|
|
98
|
+
创建 Channel 并声明 Exchange。此方法应在目标事件循环中运行。
|
|
99
|
+
Create channel and declare exchange. This should be run in the target event loop.
|
|
100
|
+
"""
|
|
101
|
+
try:
|
|
102
|
+
self._channel = await self._connection.channel()
|
|
103
|
+
self._exchange = await self._channel.declare_exchange(
|
|
104
|
+
self._exchange_name, ExchangeType.TOPIC, durable=True
|
|
105
|
+
)
|
|
106
|
+
app_logger.info(
|
|
107
|
+
"RabbitMQHandler initialized for service '%s' on exchange '%s'",
|
|
108
|
+
self._service_name,
|
|
109
|
+
self._exchange_name,
|
|
110
|
+
)
|
|
111
|
+
except Exception as e:
|
|
112
|
+
app_logger.error("Failed to initialize RabbitMQHandler: %s", e, exc_info=True)
|
|
113
|
+
# 在这里可以更优雅地处理错误,例如设置一个失败状态
|
|
114
|
+
# You might want to handle this more gracefully, e.g., by setting a failed state.
|
|
115
|
+
|
|
116
|
+
def emit(self, record: logging.LogRecord) -> None:
|
|
117
|
+
"""
|
|
118
|
+
格式化日志记录,并将其调度到事件循环上进行发布。
|
|
119
|
+
这是从同步的 logging 调用到异步世界的桥梁。
|
|
120
|
+
|
|
121
|
+
Formats the log record and schedules it for publishing on the event loop.
|
|
122
|
+
This is the bridge from the synchronous logging call to the asynchronous world.
|
|
123
|
+
"""
|
|
124
|
+
try:
|
|
125
|
+
# 将日志级别字符串转换为枚举成员
|
|
126
|
+
# Convert log level string to the enum member
|
|
127
|
+
level = LogLevelEnum(record.levelname.upper())
|
|
128
|
+
except (KeyError, ValueError):
|
|
129
|
+
# 对自定义日志级别,默认使用 INFO
|
|
130
|
+
# Default to INFO for custom log levels
|
|
131
|
+
level = LogLevelEnum.INFO
|
|
132
|
+
|
|
133
|
+
try:
|
|
134
|
+
# 构建日志事件模型和路由键
|
|
135
|
+
# Build the log event model and routing key
|
|
136
|
+
event = self._build_log_event(record, level)
|
|
137
|
+
routing_key = build_log_routing_key(self._routing_template, self._service_name, level)
|
|
138
|
+
|
|
139
|
+
# 线程安全地在事件循环中调度发布任务
|
|
140
|
+
# Thread-safely schedule the publish task in the event loop
|
|
141
|
+
future = asyncio.run_coroutine_threadsafe(self._publish(event, routing_key), self._loop)
|
|
142
|
+
|
|
143
|
+
# 追踪待处理的 future,以便在关闭时可以等待它们
|
|
144
|
+
# Track the pending future so we can wait for it on close
|
|
145
|
+
with self._pending_lock:
|
|
146
|
+
self._pending_futures.add(future)
|
|
147
|
+
future.add_done_callback(self._on_future_done)
|
|
148
|
+
|
|
149
|
+
except Exception:
|
|
150
|
+
self.handleError(record)
|
|
151
|
+
|
|
152
|
+
def _on_future_done(self, future: Future) -> None:
|
|
153
|
+
"""
|
|
154
|
+
当一个 future 完成时的回调,将其从待处理集合中移除。
|
|
155
|
+
Callback for when a future is done to remove it from the pending set.
|
|
156
|
+
"""
|
|
157
|
+
with self._pending_lock:
|
|
158
|
+
self._pending_futures.discard(future)
|
|
159
|
+
try:
|
|
160
|
+
# 调用 result() 可以触发并记录在协程中发生的任何异常
|
|
161
|
+
# Calling result() can trigger and log any exceptions that occurred in the coroutine
|
|
162
|
+
future.result()
|
|
163
|
+
except Exception as e:
|
|
164
|
+
# 这是 `_publish` 协程中的异常浮现的地方
|
|
165
|
+
# This is where exceptions from the `_publish` coroutine will be surfaced.
|
|
166
|
+
app_logger.warning("Failed to publish log to RabbitMQ: %s", e)
|
|
167
|
+
|
|
168
|
+
async def _publish(self, event: LogEventCreate, routing_key: str) -> None:
|
|
169
|
+
"""
|
|
170
|
+
实际执行消息发布的协程。
|
|
171
|
+
The actual coroutine that publishes the message.
|
|
172
|
+
"""
|
|
173
|
+
if not self._exchange:
|
|
174
|
+
# 如果初始化失败或仍在进行中,exchange 可能不可用
|
|
175
|
+
# This can happen if initialization failed or is still in progress.
|
|
176
|
+
app_logger.warning("RabbitMQ exchange not available, dropping log message.")
|
|
177
|
+
return
|
|
178
|
+
|
|
179
|
+
# 序列化并创建 aio_pika 消息对象
|
|
180
|
+
# Serialize and create an aio_pika message object
|
|
181
|
+
body = orjson.dumps(event.model_dump(mode="json"))
|
|
182
|
+
message = Message(
|
|
183
|
+
body=body,
|
|
184
|
+
delivery_mode=DeliveryMode.PERSISTENT,
|
|
185
|
+
content_type="application/json",
|
|
186
|
+
)
|
|
187
|
+
# 发布消息
|
|
188
|
+
# Publish the message
|
|
189
|
+
await self._exchange.publish(message, routing_key=routing_key, mandatory=False)
|
|
190
|
+
|
|
191
|
+
def _build_log_event(self, record: logging.LogRecord, level: LogLevelEnum) -> LogEventCreate:
|
|
192
|
+
"""
|
|
193
|
+
从 logging.LogRecord 构建一个 LogEventCreate Pydantic 模型。
|
|
194
|
+
Constructs a LogEventCreate Pydantic model from a LogRecord.
|
|
195
|
+
"""
|
|
196
|
+
return LogEventCreate(
|
|
197
|
+
event_id=generate(size=16),
|
|
198
|
+
service_name=self._service_name,
|
|
199
|
+
instance_id=self._instance_id,
|
|
200
|
+
level=level,
|
|
201
|
+
message=record.getMessage(),
|
|
202
|
+
timestamp=datetime.fromtimestamp(record.created, tz=timezone.utc),
|
|
203
|
+
ip=self._resolve_ip(),
|
|
204
|
+
host=self._host,
|
|
205
|
+
logger_name=record.name,
|
|
206
|
+
file=record.pathname,
|
|
207
|
+
line_no=record.lineno,
|
|
208
|
+
func_name=record.funcName,
|
|
209
|
+
trace_id=get_request_id(),
|
|
210
|
+
metadata=self._collect_metadata(record),
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
def _collect_metadata(self, record: logging.LogRecord) -> Dict[str, Any]:
|
|
214
|
+
"""
|
|
215
|
+
从日志记录中收集并字符串化元数据。
|
|
216
|
+
Collects and stringifies metadata from the log record.
|
|
217
|
+
"""
|
|
218
|
+
metadata: Dict[str, Any] = {
|
|
219
|
+
"module": record.module,
|
|
220
|
+
"process": record.process,
|
|
221
|
+
"thread": record.thread,
|
|
222
|
+
}
|
|
223
|
+
# 添加传递给 logger 的任何额外字段,确保它们是可序列化的
|
|
224
|
+
# Add any extra fields passed to the logger, ensuring they are serializable.
|
|
225
|
+
standard_keys = {"args", "asctime", "created", "exc_info", "exc_text", "filename", "funcName",
|
|
226
|
+
"levelname", "levelno", "lineno", "module", "msecs", "message", "msg", "name",
|
|
227
|
+
"pathname", "process", "processName", "relativeCreated", "stack_info", "thread",
|
|
228
|
+
"threadName"}
|
|
229
|
+
for key, value in record.__dict__.items():
|
|
230
|
+
if key not in standard_keys:
|
|
231
|
+
metadata[key] = str(value) # 为安全起见,进行简单的字符串转换
|
|
232
|
+
return metadata
|
|
233
|
+
|
|
234
|
+
def _resolve_ip(self) -> str:
|
|
235
|
+
"""
|
|
236
|
+
解析主机的非环回 IP 地址。
|
|
237
|
+
Resolves the primary non-loopback IP address of the host.
|
|
238
|
+
"""
|
|
239
|
+
if self._cached_ip:
|
|
240
|
+
return self._cached_ip
|
|
241
|
+
try:
|
|
242
|
+
# 连接到一个公共 DNS 服务器以找到主出站 IP
|
|
243
|
+
# Connect to a public DNS server to find the primary outbound IP
|
|
244
|
+
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
|
|
245
|
+
s.settimeout(0.1)
|
|
246
|
+
s.connect(("8.8.8.8", 80))
|
|
247
|
+
ip_addr = s.getsockname()[0]
|
|
248
|
+
except Exception:
|
|
249
|
+
ip_addr = "127.0.0.1"
|
|
250
|
+
self._cached_ip = ip_addr
|
|
251
|
+
return ip_addr
|
|
252
|
+
|
|
253
|
+
async def close_async(self) -> None:
|
|
254
|
+
"""
|
|
255
|
+
优雅地关闭 Channel。
|
|
256
|
+
Gracefully close the channel.
|
|
257
|
+
"""
|
|
258
|
+
if self._channel and not self._channel.is_closed:
|
|
259
|
+
await self._channel.close()
|
|
260
|
+
app_logger.info("RabbitMQ channel closed.")
|
|
261
|
+
|
|
262
|
+
def close(self) -> None:
|
|
263
|
+
"""
|
|
264
|
+
关闭处理器,并等待任何待处理的日志消息被发送。
|
|
265
|
+
Closes the handler, waiting for any pending log messages to be sent.
|
|
266
|
+
"""
|
|
267
|
+
# 等待待处理的 futures 完成
|
|
268
|
+
# Wait for pending futures to complete
|
|
269
|
+
pending = list(self._pending_futures)
|
|
270
|
+
if pending:
|
|
271
|
+
# 这是一个同步上下文,所以我们不能 await
|
|
272
|
+
# 我们在这里能做的就是记录下我们正在放弃待处理的消息
|
|
273
|
+
# This is a synchronous context, so we can't await.
|
|
274
|
+
# We can't do much here other than log that we are abandoning pending messages.
|
|
275
|
+
app_logger.info("Closing RabbitMQHandler with %d pending messages.", len(pending))
|
|
276
|
+
|
|
277
|
+
if self._loop.is_running():
|
|
278
|
+
asyncio.run_coroutine_threadsafe(self.close_async(), self._loop)
|
|
279
|
+
super().close()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Shared schema models provided by Cancan Microstack."""
|
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Caddy 相关的 Pydantic 类型定义
|
|
3
|
+
"""
|
|
4
|
+
from typing import (
|
|
5
|
+
Any,
|
|
6
|
+
Dict,
|
|
7
|
+
List,
|
|
8
|
+
Optional,
|
|
9
|
+
)
|
|
10
|
+
from datetime import datetime
|
|
11
|
+
from pydantic import (
|
|
12
|
+
BaseModel,
|
|
13
|
+
ConfigDict,
|
|
14
|
+
Field,
|
|
15
|
+
)
|
|
16
|
+
from decimal import Decimal
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# ==================== Caddy Route(路由) ====================
|
|
20
|
+
|
|
21
|
+
class CaddyRouteCreate(BaseModel):
|
|
22
|
+
"""创建路由的请求模型"""
|
|
23
|
+
route_name: str = Field(..., description="路由名称(唯一标识)", min_length=1, max_length=100)
|
|
24
|
+
domain: str = Field(..., description="域名", min_length=1, max_length=255)
|
|
25
|
+
path_pattern: str = Field(..., description="路径匹配模式", min_length=1, max_length=500)
|
|
26
|
+
upstream_service: str = Field(..., description="上游服务名称", min_length=1, max_length=100)
|
|
27
|
+
upstream_host: str = Field(..., description="上游主机", min_length=1, max_length=100)
|
|
28
|
+
upstream_port: int = Field(..., description="上游端口", ge=1, le=65535)
|
|
29
|
+
strip_path_prefix: Optional[str] = Field(None, description="去除路径前缀", max_length=200)
|
|
30
|
+
add_path_prefix: Optional[str] = Field(None, description="添加路径前缀", max_length=200)
|
|
31
|
+
enable_https: bool = Field(default=True, description="是否启用 HTTPS")
|
|
32
|
+
force_https: bool = Field(default=True, description="是否强制 HTTPS")
|
|
33
|
+
enable_waf: bool = Field(default=True, description="是否启用 WAF")
|
|
34
|
+
waf_rule_set: str = Field(default="default", description="WAF 规则集")
|
|
35
|
+
load_balance_strategy: str = Field("round_robin", description="负载均衡策略")
|
|
36
|
+
health_check_path: Optional[str] = Field(default=None, description="健康检查路径", max_length=200)
|
|
37
|
+
health_check_interval: int = Field(default=30, description="健康检查间隔(秒)", ge=5)
|
|
38
|
+
is_enabled: bool = Field(default=True, description="是否启用")
|
|
39
|
+
priority: int = Field(default=100, description="优先级", ge=0)
|
|
40
|
+
route_metadata: Optional[Dict[str, Any]] = Field(default=None, description="路由附加元数据")
|
|
41
|
+
description: Optional[str] = Field(default=None, description="路由描述")
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class CaddyRouteUpdate(BaseModel):
|
|
45
|
+
"""更新路由的请求模型(所有字段可选)"""
|
|
46
|
+
domain: Optional[str] = Field(None, description="域名", min_length=1, max_length=255)
|
|
47
|
+
path_pattern: Optional[str] = Field(None, description="路径匹配模式", min_length=1, max_length=500)
|
|
48
|
+
upstream_service: Optional[str] = Field(None, description="上游服务名称", min_length=1, max_length=100)
|
|
49
|
+
upstream_host: Optional[str] = Field(None, description="上游主机", min_length=1, max_length=100)
|
|
50
|
+
upstream_port: Optional[int] = Field(None, description="上游端口", ge=1, le=65535)
|
|
51
|
+
strip_path_prefix: Optional[str] = Field(None, description="去除路径前缀", max_length=200)
|
|
52
|
+
add_path_prefix: Optional[str] = Field(None, description="添加路径前缀", max_length=200)
|
|
53
|
+
enable_https: Optional[bool] = Field(None, description="是否启用 HTTPS")
|
|
54
|
+
force_https: Optional[bool] = Field(None, description="是否强制 HTTPS")
|
|
55
|
+
enable_waf: Optional[bool] = Field(None, description="是否启用 WAF")
|
|
56
|
+
waf_rule_set: Optional[str] = Field(None, description="WAF 规则集")
|
|
57
|
+
load_balance_strategy: Optional[str] = Field(None, description="负载均衡策略")
|
|
58
|
+
health_check_path: Optional[str] = Field(None, description="健康检查路径", max_length=200)
|
|
59
|
+
health_check_interval: Optional[int] = Field(None, description="健康检查间隔(秒)", ge=5)
|
|
60
|
+
is_enabled: Optional[bool] = Field(None, description="是否启用")
|
|
61
|
+
priority: Optional[int] = Field(None, description="优先级", ge=0)
|
|
62
|
+
route_metadata: Optional[Dict[str, Any]] = Field(None, description="路由附加元数据")
|
|
63
|
+
description: Optional[str] = Field(None, description="路由描述")
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class CaddyRoute(BaseModel):
|
|
67
|
+
"""路由数据模型"""
|
|
68
|
+
|
|
69
|
+
model_config = ConfigDict(from_attributes=True)
|
|
70
|
+
|
|
71
|
+
id: Optional[int] = None
|
|
72
|
+
route_name: str
|
|
73
|
+
domain: str
|
|
74
|
+
path_pattern: str
|
|
75
|
+
upstream_service: str
|
|
76
|
+
upstream_host: str
|
|
77
|
+
upstream_port: int
|
|
78
|
+
strip_path_prefix: Optional[str] = None
|
|
79
|
+
add_path_prefix: Optional[str] = None
|
|
80
|
+
enable_https: bool = True
|
|
81
|
+
force_https: bool = True
|
|
82
|
+
enable_waf: bool = True
|
|
83
|
+
waf_rule_set: str = "default"
|
|
84
|
+
load_balance_strategy: str = "round_robin"
|
|
85
|
+
health_check_path: Optional[str] = None
|
|
86
|
+
health_check_interval: int = 30
|
|
87
|
+
is_enabled: bool = True
|
|
88
|
+
priority: int = 100
|
|
89
|
+
route_metadata: Optional[Dict[str, Any]] = None
|
|
90
|
+
description: Optional[str] = None
|
|
91
|
+
created_time: Optional[datetime] = None
|
|
92
|
+
update_time: Optional[datetime] = None
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
# ==================== Caddy Rate Limit(限流) ====================
|
|
97
|
+
|
|
98
|
+
class CaddyRateLimitCreate(BaseModel):
|
|
99
|
+
"""创建限流规则的请求模型"""
|
|
100
|
+
rule_name: str = Field(..., description="规则名称(唯一标识)", min_length=1, max_length=100)
|
|
101
|
+
description: Optional[str] = Field(None, description="规则描述")
|
|
102
|
+
match_type: str = Field(..., description="匹配类型(path/domain/ip/header/all)")
|
|
103
|
+
match_pattern: Optional[str] = Field(None, description="匹配模式", max_length=500)
|
|
104
|
+
match_domain: Optional[str] = Field(None, description="匹配域名", max_length=255)
|
|
105
|
+
limit_type: str = Field("request", description="限流类型(request/bandwidth)")
|
|
106
|
+
limit_value: int = Field(..., description="限流值", ge=1)
|
|
107
|
+
limit_window: int = Field(60, description="时间窗口(秒)", ge=1)
|
|
108
|
+
limit_key: str = Field("ip", description="限流键(ip/header/cookie/path)")
|
|
109
|
+
burst_size: int = Field(0, description="突发流量大小", ge=0)
|
|
110
|
+
block_status_code: int = Field(429, description="被限流时的状态码", ge=100, le=599)
|
|
111
|
+
block_message: str = Field("Too Many Requests", description="被限流时的消息", max_length=500)
|
|
112
|
+
whitelist_ips: Optional[List[str]] = Field(None, description="IP 白名单")
|
|
113
|
+
blacklist_ips: Optional[List[str]] = Field(None, description="IP 黑名单")
|
|
114
|
+
is_enabled: bool = Field(True, description="是否启用")
|
|
115
|
+
priority: int = Field(100, description="优先级", ge=0)
|
|
116
|
+
rule_metadata: Optional[Dict[str, Any]] = Field(default=None, description="限流附加元数据")
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class CaddyRateLimitUpdate(BaseModel):
|
|
120
|
+
"""更新限流规则的请求模型(所有字段可选)"""
|
|
121
|
+
description: Optional[str] = Field(None, description="规则描述")
|
|
122
|
+
match_type: Optional[str] = Field(None, description="匹配类型(path/domain/ip/header/all)")
|
|
123
|
+
match_pattern: Optional[str] = Field(None, description="匹配模式", max_length=500)
|
|
124
|
+
match_domain: Optional[str] = Field(None, description="匹配域名", max_length=255)
|
|
125
|
+
limit_type: Optional[str] = Field(None, description="限流类型(request/bandwidth)")
|
|
126
|
+
limit_value: Optional[int] = Field(None, description="限流值", ge=1)
|
|
127
|
+
limit_window: Optional[int] = Field(None, description="时间窗口(秒)", ge=1)
|
|
128
|
+
limit_key: Optional[str] = Field(None, description="限流键(ip/header/cookie/path)")
|
|
129
|
+
burst_size: Optional[int] = Field(None, description="突发流量大小", ge=0)
|
|
130
|
+
block_status_code: Optional[int] = Field(None, description="被限流时的状态码", ge=100, le=599)
|
|
131
|
+
block_message: Optional[str] = Field(None, description="被限流时的消息", max_length=500)
|
|
132
|
+
whitelist_ips: Optional[List[str]] = Field(None, description="IP 白名单")
|
|
133
|
+
blacklist_ips: Optional[List[str]] = Field(None, description="IP 黑名单")
|
|
134
|
+
is_enabled: Optional[bool] = Field(None, description="是否启用")
|
|
135
|
+
priority: Optional[int] = Field(None, description="优先级", ge=0)
|
|
136
|
+
rule_metadata: Optional[Dict[str, Any]] = Field(None, description="限流附加元数据")
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
class CaddyRateLimit(BaseModel):
|
|
140
|
+
"""限流规则数据模型"""
|
|
141
|
+
|
|
142
|
+
model_config = ConfigDict(from_attributes=True)
|
|
143
|
+
|
|
144
|
+
id: Optional[int] = None
|
|
145
|
+
rule_name: str
|
|
146
|
+
description: Optional[str] = None
|
|
147
|
+
match_type: str
|
|
148
|
+
match_pattern: Optional[str] = None
|
|
149
|
+
match_domain: Optional[str] = None
|
|
150
|
+
limit_type: str = "request"
|
|
151
|
+
limit_value: int
|
|
152
|
+
limit_window: int = 60
|
|
153
|
+
limit_key: str = "ip"
|
|
154
|
+
burst_size: int = 0
|
|
155
|
+
block_status_code: int = 429
|
|
156
|
+
block_message: str = "Too Many Requests"
|
|
157
|
+
whitelist_ips: Optional[List[str]] = None
|
|
158
|
+
blacklist_ips: Optional[List[str]] = None
|
|
159
|
+
is_enabled: bool = True
|
|
160
|
+
priority: int = 100
|
|
161
|
+
rule_metadata: Optional[Dict[str, Any]] = None
|
|
162
|
+
created_time: Optional[datetime] = None
|
|
163
|
+
update_time: Optional[datetime] = None
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
# ==================== Caddy Access Log(访问日志) ====================
|
|
168
|
+
|
|
169
|
+
class CaddyAccessLog(BaseModel):
|
|
170
|
+
"""访问日志数据模型"""
|
|
171
|
+
|
|
172
|
+
model_config = ConfigDict(from_attributes=True)
|
|
173
|
+
|
|
174
|
+
id: Optional[int] = None
|
|
175
|
+
request_id: str
|
|
176
|
+
timestamp: datetime
|
|
177
|
+
client_ip: str
|
|
178
|
+
client_port: Optional[int] = None
|
|
179
|
+
user_agent: Optional[str] = None
|
|
180
|
+
referer: Optional[str] = None
|
|
181
|
+
country: Optional[str] = None
|
|
182
|
+
country_code: Optional[str] = None
|
|
183
|
+
region: Optional[str] = None
|
|
184
|
+
city: Optional[str] = None
|
|
185
|
+
latitude: Optional[Decimal] = None
|
|
186
|
+
longitude: Optional[Decimal] = None
|
|
187
|
+
timezone: Optional[str] = None
|
|
188
|
+
isp: Optional[str] = None
|
|
189
|
+
method: str
|
|
190
|
+
protocol: Optional[str] = None
|
|
191
|
+
host: Optional[str] = None
|
|
192
|
+
path: str
|
|
193
|
+
query_string: Optional[str] = None
|
|
194
|
+
matched_route: Optional[str] = None
|
|
195
|
+
upstream_service: Optional[str] = None
|
|
196
|
+
upstream_host: Optional[str] = None
|
|
197
|
+
upstream_port: Optional[int] = None
|
|
198
|
+
status_code: int
|
|
199
|
+
response_size: Optional[int] = None
|
|
200
|
+
response_time: Optional[int] = None
|
|
201
|
+
waf_action: Optional[str] = None
|
|
202
|
+
waf_rule_id: Optional[str] = None
|
|
203
|
+
waf_score: Optional[int] = None
|
|
204
|
+
rate_limited: bool = False
|
|
205
|
+
rate_limit_rule: Optional[str] = None
|
|
206
|
+
tls_version: Optional[str] = None
|
|
207
|
+
tls_cipher: Optional[str] = None
|
|
208
|
+
log_metadata: Optional[Dict[str, Any]] = None
|
|
209
|
+
created_time: Optional[datetime] = None
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
# ==================== Caddy Stats(统计) ====================
|
|
214
|
+
|
|
215
|
+
class CaddyStats(BaseModel):
|
|
216
|
+
"""统计数据模型"""
|
|
217
|
+
|
|
218
|
+
model_config = ConfigDict(from_attributes=True)
|
|
219
|
+
|
|
220
|
+
id: Optional[int] = None
|
|
221
|
+
stat_time: datetime
|
|
222
|
+
stat_period: str
|
|
223
|
+
dimension_type: str
|
|
224
|
+
dimension_value: Optional[str] = None
|
|
225
|
+
total_requests: int = 0
|
|
226
|
+
success_requests: int = 0
|
|
227
|
+
client_error_requests: int = 0
|
|
228
|
+
server_error_requests: int = 0
|
|
229
|
+
total_bytes_sent: int = 0
|
|
230
|
+
total_bytes_received: int = 0
|
|
231
|
+
avg_response_time: Optional[int] = None
|
|
232
|
+
min_response_time: Optional[int] = None
|
|
233
|
+
max_response_time: Optional[int] = None
|
|
234
|
+
p50_response_time: Optional[int] = None
|
|
235
|
+
p95_response_time: Optional[int] = None
|
|
236
|
+
p99_response_time: Optional[int] = None
|
|
237
|
+
waf_blocked_requests: int = 0
|
|
238
|
+
waf_logged_requests: int = 0
|
|
239
|
+
rate_limited_requests: int = 0
|
|
240
|
+
tls_requests: int = 0
|
|
241
|
+
non_tls_requests: int = 0
|
|
242
|
+
unique_ips: int = 0
|
|
243
|
+
unique_user_agents: int = 0
|
|
244
|
+
stats_metadata: Optional[Dict[str, Any]] = None
|
|
245
|
+
created_time: Optional[datetime] = None
|
|
246
|
+
update_time: Optional[datetime] = None
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
class RealtimeStatsResponse(BaseModel):
|
|
251
|
+
"""实时统计响应模型
|
|
252
|
+
Realtime statistics response model
|
|
253
|
+
"""
|
|
254
|
+
|
|
255
|
+
stats: Optional[CaddyStats] = Field(default=None, description="统计数据 / Statistics payload")
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
class GlobalTrendResponse(BaseModel):
|
|
259
|
+
"""全局趋势响应模型
|
|
260
|
+
Global trend response model
|
|
261
|
+
"""
|
|
262
|
+
|
|
263
|
+
period: str = Field(..., description="统计周期(hourly/daily/monthly)/ Aggregation period")
|
|
264
|
+
hours: int = Field(..., description="聚合的小时数 / Number of aggregated hours")
|
|
265
|
+
trend: List[CaddyStats] = Field(default_factory=list, description="统计数据序列 / Statistics series")
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
class ServiceTrendResponse(GlobalTrendResponse):
|
|
269
|
+
"""服务趋势响应模型
|
|
270
|
+
Service trend response model
|
|
271
|
+
"""
|
|
272
|
+
|
|
273
|
+
service_name: str = Field(..., description="服务名称 / Service name")
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
class RouteTrendResponse(GlobalTrendResponse):
|
|
277
|
+
"""路由趋势响应模型
|
|
278
|
+
Route trend response model
|
|
279
|
+
"""
|
|
280
|
+
|
|
281
|
+
route_id: int = Field(..., description="路由 ID / Route identifier")
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
class TopDimensionResponse(BaseModel):
|
|
285
|
+
"""Top 维度统计响应模型
|
|
286
|
+
Top dimension statistics response model
|
|
287
|
+
"""
|
|
288
|
+
|
|
289
|
+
period: str = Field(..., description="统计周期 / Aggregation period")
|
|
290
|
+
limit: int = Field(..., description="返回数量上限 / Maximum number of items")
|
|
291
|
+
items: List[CaddyStats] = Field(default_factory=list, description="统计项列表 / Statistics items")
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
class CleanupStatsResponse(BaseModel):
|
|
295
|
+
"""统计数据清理结果模型
|
|
296
|
+
Cleanup statistics response model
|
|
297
|
+
"""
|
|
298
|
+
|
|
299
|
+
message: str = Field(..., description="执行结果信息 / Result message")
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
# ==================== Caddy Certificate(证书) ====================
|
|
303
|
+
|
|
304
|
+
class CaddyCertificateCreate(BaseModel):
|
|
305
|
+
"""创建证书的请求模型"""
|
|
306
|
+
domain: str = Field(..., description="主域名", min_length=1, max_length=255)
|
|
307
|
+
alt_domains: Optional[List[str]] = Field(None, description="备用域名列表")
|
|
308
|
+
auto_renew: bool = Field(True, description="是否自动续期")
|
|
309
|
+
renew_before_days: int = Field(30, description="提前多少天续期", ge=1, le=90)
|
|
310
|
+
acme_provider: str = Field("letsencrypt", description="ACME 提供商")
|
|
311
|
+
acme_email: Optional[str] = Field(None, description="ACME 邮箱", max_length=255)
|
|
312
|
+
acme_challenge_type: str = Field("http-01", description="ACME 挑战类型(http-01/dns-01)")
|
|
313
|
+
certificate_metadata: Optional[Dict[str, Any]] = Field(None, description="证书附加元数据")
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
class CaddyCertificateUpdate(BaseModel):
|
|
317
|
+
"""更新证书的请求模型(所有字段可选)"""
|
|
318
|
+
alt_domains: Optional[List[str]] = Field(None, description="备用域名列表")
|
|
319
|
+
auto_renew: Optional[bool] = Field(None, description="是否自动续期")
|
|
320
|
+
renew_before_days: Optional[int] = Field(None, description="提前多少天续期", ge=1, le=90)
|
|
321
|
+
acme_provider: Optional[str] = Field(None, description="ACME 提供商")
|
|
322
|
+
acme_email: Optional[str] = Field(None, description="ACME 邮箱", max_length=255)
|
|
323
|
+
acme_challenge_type: Optional[str] = Field(None, description="ACME 挑战类型(http-01/dns-01)")
|
|
324
|
+
certificate_metadata: Optional[Dict[str, Any]] = Field(None, description="证书附加元数据")
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
class CaddyCertificate(BaseModel):
|
|
328
|
+
"""证书数据模型"""
|
|
329
|
+
|
|
330
|
+
model_config = ConfigDict(from_attributes=True)
|
|
331
|
+
|
|
332
|
+
id: Optional[int] = None
|
|
333
|
+
domain: str
|
|
334
|
+
alt_domains: Optional[List[str]] = None
|
|
335
|
+
certificate_pem: Optional[str] = None
|
|
336
|
+
private_key_pem: Optional[str] = None
|
|
337
|
+
issuer: Optional[str] = None
|
|
338
|
+
issued_at: Optional[datetime] = None
|
|
339
|
+
expires_at: Optional[datetime] = None
|
|
340
|
+
auto_renew: bool = True
|
|
341
|
+
renew_before_days: int = 30
|
|
342
|
+
status: str = "pending"
|
|
343
|
+
last_renew_attempt: Optional[datetime] = None
|
|
344
|
+
last_renew_success: Optional[datetime] = None
|
|
345
|
+
renew_error: Optional[str] = None
|
|
346
|
+
acme_provider: str = "letsencrypt"
|
|
347
|
+
acme_email: Optional[str] = None
|
|
348
|
+
acme_challenge_type: str = "http-01"
|
|
349
|
+
certificate_metadata: Optional[Dict[str, Any]] = None
|
|
350
|
+
created_time: Optional[datetime] = None
|
|
351
|
+
update_time: Optional[datetime] = None
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
# ==================== 查询参数模型 ====================
|
|
356
|
+
|
|
357
|
+
class AccessLogQuery(BaseModel):
|
|
358
|
+
"""访问日志查询参数"""
|
|
359
|
+
client_ip: Optional[str] = Field(default=None, description="客户端 IP")
|
|
360
|
+
country: Optional[str] = Field(default=None, description="国家")
|
|
361
|
+
country_code: Optional[str] = Field(default=None, description="国家代码")
|
|
362
|
+
upstream_service: Optional[str] = Field(default=None, description="上游服务")
|
|
363
|
+
matched_route: Optional[str] = Field(default=None, description="匹配的路由")
|
|
364
|
+
waf_action: Optional[str] = Field(default=None, description="WAF 动作")
|
|
365
|
+
rate_limited: Optional[bool] = Field(default=None, description="是否被限流")
|
|
366
|
+
min_response_time: Optional[int] = Field(default=None, description="最小响应时间(毫秒)")
|
|
367
|
+
max_response_time: Optional[int] = Field(default=None, description="最大响应时间(毫秒)")
|
|
368
|
+
start_time: Optional[datetime] = Field(default=None, description="开始时间")
|
|
369
|
+
end_time: Optional[datetime] = Field(default=None, description="结束时间")
|
|
370
|
+
limit: int = Field(default=100, description="返回数量限制", ge=1, le=1000)
|
|
371
|
+
offset: int = Field(default=0, description="偏移量", ge=0)
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
class StatsQuery(BaseModel):
|
|
375
|
+
"""统计数据查询参数"""
|
|
376
|
+
stat_period: Optional[str] = Field(None, description="统计周期(minute/hour/day/month)")
|
|
377
|
+
dimension_type: Optional[str] = Field(None, description="维度类型(global/service/route/ip/country)")
|
|
378
|
+
dimension_value: Optional[str] = Field(None, description="维度值")
|
|
379
|
+
start_time: Optional[datetime] = Field(None, description="开始时间")
|
|
380
|
+
end_time: Optional[datetime] = Field(None, description="结束时间")
|
|
381
|
+
limit: int = Field(100, description="返回数量限制", ge=1, le=1000)
|