django-cfg 1.5.8__py3-none-any.whl → 1.5.14__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.
Potentially problematic release.
This version of django-cfg might be problematic. Click here for more details.
- django_cfg/__init__.py +1 -1
- django_cfg/apps/api/commands/serializers.py +152 -0
- django_cfg/apps/api/commands/views.py +32 -0
- django_cfg/apps/business/accounts/management/commands/otp_test.py +5 -2
- django_cfg/apps/business/agents/management/commands/create_agent.py +5 -194
- django_cfg/apps/business/agents/management/commands/load_agent_templates.py +205 -0
- django_cfg/apps/business/agents/management/commands/orchestrator_status.py +4 -2
- django_cfg/apps/business/knowbase/management/commands/knowbase_stats.py +4 -2
- django_cfg/apps/business/knowbase/management/commands/setup_knowbase.py +4 -2
- django_cfg/apps/business/newsletter/management/commands/test_newsletter.py +5 -2
- django_cfg/apps/business/payments/management/commands/check_payment_status.py +4 -2
- django_cfg/apps/business/payments/management/commands/create_payment.py +4 -2
- django_cfg/apps/business/payments/management/commands/sync_currencies.py +4 -2
- django_cfg/apps/integrations/centrifugo/management/commands/generate_centrifugo_clients.py +5 -5
- django_cfg/apps/integrations/centrifugo/serializers/__init__.py +2 -1
- django_cfg/apps/integrations/centrifugo/serializers/publishes.py +22 -2
- django_cfg/apps/integrations/centrifugo/views/monitoring.py +25 -40
- django_cfg/apps/integrations/grpc/admin/__init__.py +7 -1
- django_cfg/apps/integrations/grpc/admin/config.py +113 -9
- django_cfg/apps/integrations/grpc/admin/grpc_api_key.py +129 -0
- django_cfg/apps/integrations/grpc/admin/grpc_request_log.py +72 -63
- django_cfg/apps/integrations/grpc/admin/grpc_server_status.py +236 -0
- django_cfg/apps/integrations/grpc/auth/__init__.py +11 -3
- django_cfg/apps/integrations/grpc/auth/api_key_auth.py +320 -0
- django_cfg/apps/integrations/grpc/interceptors/logging.py +17 -20
- django_cfg/apps/integrations/grpc/interceptors/metrics.py +15 -14
- django_cfg/apps/integrations/grpc/interceptors/request_logger.py +79 -59
- django_cfg/apps/integrations/grpc/management/commands/generate_protos.py +130 -0
- django_cfg/apps/integrations/grpc/management/commands/rungrpc.py +171 -96
- django_cfg/apps/integrations/grpc/management/commands/test_grpc_integration.py +75 -0
- django_cfg/apps/integrations/grpc/managers/__init__.py +2 -0
- django_cfg/apps/integrations/grpc/managers/grpc_api_key.py +192 -0
- django_cfg/apps/integrations/grpc/managers/grpc_server_status.py +19 -11
- django_cfg/apps/integrations/grpc/migrations/0005_grpcapikey.py +143 -0
- django_cfg/apps/integrations/grpc/migrations/0006_grpcrequestlog_api_key_and_more.py +34 -0
- django_cfg/apps/integrations/grpc/models/__init__.py +2 -0
- django_cfg/apps/integrations/grpc/models/grpc_api_key.py +198 -0
- django_cfg/apps/integrations/grpc/models/grpc_request_log.py +11 -0
- django_cfg/apps/integrations/grpc/models/grpc_server_status.py +39 -4
- django_cfg/apps/integrations/grpc/serializers/__init__.py +22 -6
- django_cfg/apps/integrations/grpc/serializers/api_keys.py +63 -0
- django_cfg/apps/integrations/grpc/serializers/charts.py +118 -120
- django_cfg/apps/integrations/grpc/serializers/config.py +65 -51
- django_cfg/apps/integrations/grpc/serializers/health.py +7 -7
- django_cfg/apps/integrations/grpc/serializers/proto_files.py +74 -0
- django_cfg/apps/integrations/grpc/serializers/requests.py +13 -7
- django_cfg/apps/integrations/grpc/serializers/service_registry.py +181 -112
- django_cfg/apps/integrations/grpc/serializers/services.py +14 -32
- django_cfg/apps/integrations/grpc/serializers/stats.py +50 -12
- django_cfg/apps/integrations/grpc/serializers/testing.py +66 -58
- django_cfg/apps/integrations/grpc/services/__init__.py +2 -0
- django_cfg/apps/integrations/grpc/services/monitoring_service.py +149 -43
- django_cfg/apps/integrations/grpc/services/proto_files_manager.py +268 -0
- django_cfg/apps/integrations/grpc/services/service_registry.py +48 -46
- django_cfg/apps/integrations/grpc/services/testing_service.py +10 -15
- django_cfg/apps/integrations/grpc/urls.py +8 -0
- django_cfg/apps/integrations/grpc/utils/__init__.py +4 -13
- django_cfg/apps/integrations/grpc/utils/integration_test.py +334 -0
- django_cfg/apps/integrations/grpc/utils/proto_gen.py +48 -8
- django_cfg/apps/integrations/grpc/utils/streaming_logger.py +177 -0
- django_cfg/apps/integrations/grpc/views/__init__.py +4 -0
- django_cfg/apps/integrations/grpc/views/api_keys.py +255 -0
- django_cfg/apps/integrations/grpc/views/charts.py +21 -14
- django_cfg/apps/integrations/grpc/views/config.py +8 -6
- django_cfg/apps/integrations/grpc/views/monitoring.py +51 -79
- django_cfg/apps/integrations/grpc/views/proto_files.py +214 -0
- django_cfg/apps/integrations/grpc/views/services.py +30 -21
- django_cfg/apps/integrations/grpc/views/testing.py +45 -43
- django_cfg/apps/integrations/rq/views/jobs.py +19 -9
- django_cfg/apps/integrations/rq/views/schedule.py +7 -3
- django_cfg/apps/system/dashboard/serializers/commands.py +25 -1
- django_cfg/apps/system/dashboard/services/commands_service.py +12 -1
- django_cfg/apps/system/maintenance/management/commands/maintenance.py +5 -2
- django_cfg/apps/system/maintenance/management/commands/process_scheduled_maintenance.py +4 -2
- django_cfg/apps/system/maintenance/management/commands/sync_cloudflare.py +5 -2
- django_cfg/config.py +33 -0
- django_cfg/core/generation/integration_generators/grpc_generator.py +30 -32
- django_cfg/management/commands/check_endpoints.py +2 -2
- django_cfg/management/commands/check_settings.py +3 -10
- django_cfg/management/commands/clear_constance.py +3 -10
- django_cfg/management/commands/create_token.py +4 -11
- django_cfg/management/commands/list_urls.py +4 -10
- django_cfg/management/commands/migrate_all.py +18 -12
- django_cfg/management/commands/migrator.py +4 -11
- django_cfg/management/commands/script.py +4 -10
- django_cfg/management/commands/show_config.py +8 -16
- django_cfg/management/commands/show_urls.py +5 -11
- django_cfg/management/commands/superuser.py +4 -11
- django_cfg/management/commands/tree.py +5 -10
- django_cfg/management/utils/README.md +402 -0
- django_cfg/management/utils/__init__.py +29 -0
- django_cfg/management/utils/mixins.py +176 -0
- django_cfg/middleware/pagination.py +53 -54
- django_cfg/models/api/grpc/__init__.py +15 -21
- django_cfg/models/api/grpc/config.py +155 -73
- django_cfg/models/ngrok/config.py +7 -6
- django_cfg/modules/django_client/core/generator/python/files_generator.py +5 -13
- django_cfg/modules/django_client/core/generator/python/templates/api_wrapper.py.jinja +16 -4
- django_cfg/modules/django_client/core/generator/python/templates/main_init.py.jinja +2 -3
- django_cfg/modules/django_client/core/generator/typescript/files_generator.py +6 -5
- django_cfg/modules/django_client/core/generator/typescript/templates/main_index.ts.jinja +12 -8
- django_cfg/modules/django_client/core/parser/base.py +114 -30
- django_cfg/modules/django_client/management/commands/generate_client.py +5 -2
- django_cfg/modules/django_client/management/commands/validate_openapi.py +5 -2
- django_cfg/modules/django_email/management/commands/test_email.py +4 -10
- django_cfg/modules/django_ngrok/management/commands/runserver_ngrok.py +16 -13
- django_cfg/modules/django_telegram/management/commands/test_telegram.py +4 -11
- django_cfg/modules/django_twilio/management/commands/test_twilio.py +4 -11
- django_cfg/modules/django_unfold/navigation.py +6 -18
- django_cfg/pyproject.toml +1 -1
- django_cfg/registry/modules.py +1 -4
- django_cfg/requirements.txt +52 -0
- django_cfg/static/frontend/admin.zip +0 -0
- {django_cfg-1.5.8.dist-info → django_cfg-1.5.14.dist-info}/METADATA +1 -1
- {django_cfg-1.5.8.dist-info → django_cfg-1.5.14.dist-info}/RECORD +118 -97
- django_cfg/apps/integrations/grpc/auth/jwt_auth.py +0 -295
- {django_cfg-1.5.8.dist-info → django_cfg-1.5.14.dist-info}/WHEEL +0 -0
- {django_cfg-1.5.8.dist-info → django_cfg-1.5.14.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.5.8.dist-info → django_cfg-1.5.14.dist-info}/licenses/LICENSE +0 -0
|
@@ -174,11 +174,17 @@ class GRPCServerStatus(models.Model):
|
|
|
174
174
|
|
|
175
175
|
@property
|
|
176
176
|
def is_running(self) -> bool:
|
|
177
|
-
"""
|
|
177
|
+
"""
|
|
178
|
+
Check if server is currently running.
|
|
179
|
+
|
|
180
|
+
Uses environment-aware detection:
|
|
181
|
+
- Production: Assumes external server (Docker), relies on heartbeat only
|
|
182
|
+
- Development/Test: Checks local process + heartbeat
|
|
183
|
+
"""
|
|
178
184
|
if self.status not in [self.StatusChoices.RUNNING, self.StatusChoices.STARTING]:
|
|
179
185
|
return False
|
|
180
186
|
|
|
181
|
-
# Check if process is still alive
|
|
187
|
+
# Check if process is still alive (auto-detects external servers)
|
|
182
188
|
if not self._is_process_alive():
|
|
183
189
|
return False
|
|
184
190
|
|
|
@@ -227,12 +233,41 @@ class GRPCServerStatus(models.Model):
|
|
|
227
233
|
return " ".join(parts)
|
|
228
234
|
|
|
229
235
|
def _is_process_alive(self) -> bool:
|
|
230
|
-
"""
|
|
236
|
+
"""
|
|
237
|
+
Check if the process is still running.
|
|
238
|
+
|
|
239
|
+
Uses environment-aware detection:
|
|
240
|
+
- Production mode: Skip PID check (assumes external server in Docker)
|
|
241
|
+
- Development/Test: Check PID with graceful fallback for containers
|
|
242
|
+
"""
|
|
243
|
+
try:
|
|
244
|
+
from django_cfg.core import get_current_config
|
|
245
|
+
|
|
246
|
+
# Auto-detect based on env_mode
|
|
247
|
+
config = get_current_config()
|
|
248
|
+
if config and str(config.env_mode) == "production":
|
|
249
|
+
# Production = external server in separate container
|
|
250
|
+
# Don't check PID, rely on heartbeat only
|
|
251
|
+
return True
|
|
252
|
+
|
|
253
|
+
except Exception:
|
|
254
|
+
# Config not available, use fallback logic
|
|
255
|
+
pass
|
|
256
|
+
|
|
257
|
+
# Development/Test or fallback: check PID with graceful handling
|
|
231
258
|
try:
|
|
232
259
|
# Send signal 0 to check if process exists
|
|
233
260
|
os.kill(self.pid, 0)
|
|
234
261
|
return True
|
|
235
|
-
except
|
|
262
|
+
except ProcessLookupError:
|
|
263
|
+
# PID not found - could be different namespace (Docker)
|
|
264
|
+
# Don't mark as dead immediately, rely on heartbeat
|
|
265
|
+
return True
|
|
266
|
+
except PermissionError:
|
|
267
|
+
# Process exists but no permission to signal
|
|
268
|
+
return True
|
|
269
|
+
except OSError:
|
|
270
|
+
# Other OS error (e.g., process died)
|
|
236
271
|
return False
|
|
237
272
|
|
|
238
273
|
def mark_running(self):
|
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
Pydantic serializers for gRPC monitoring API.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
from .api_keys import (
|
|
6
|
+
ApiKeyListSerializer,
|
|
7
|
+
ApiKeySerializer,
|
|
8
|
+
ApiKeyStatsSerializer,
|
|
9
|
+
)
|
|
10
|
+
from .proto_files import (
|
|
11
|
+
ProtoFileDetailSerializer,
|
|
12
|
+
ProtoFileListSerializer,
|
|
13
|
+
ProtoGenerateRequestSerializer,
|
|
14
|
+
ProtoGenerateResponseSerializer,
|
|
15
|
+
)
|
|
5
16
|
from .charts import (
|
|
6
17
|
DashboardChartsSerializer,
|
|
7
18
|
ErrorDistributionChartSerializer,
|
|
@@ -17,14 +28,12 @@ from .requests import RecentRequestsSerializer
|
|
|
17
28
|
from .service_registry import (
|
|
18
29
|
MethodDetailSerializer,
|
|
19
30
|
ServiceDetailSerializer,
|
|
20
|
-
ServiceListSerializer
|
|
31
|
+
ServiceListSerializer,
|
|
21
32
|
ServiceMethodsSerializer,
|
|
22
33
|
)
|
|
23
34
|
from .services import (
|
|
24
35
|
MethodListSerializer,
|
|
25
36
|
MethodStatsSerializer,
|
|
26
|
-
MonitoringServiceStatsSerializer,
|
|
27
|
-
ServiceListSerializer,
|
|
28
37
|
)
|
|
29
38
|
from .stats import GRPCOverviewStatsSerializer
|
|
30
39
|
from .testing import (
|
|
@@ -39,15 +48,13 @@ __all__ = [
|
|
|
39
48
|
"GRPCHealthCheckSerializer",
|
|
40
49
|
"GRPCOverviewStatsSerializer",
|
|
41
50
|
"RecentRequestsSerializer",
|
|
42
|
-
"MonitoringServiceStatsSerializer",
|
|
43
|
-
"ServiceListSerializer",
|
|
44
51
|
"MethodStatsSerializer",
|
|
45
52
|
"MethodListSerializer",
|
|
46
53
|
# Config
|
|
47
54
|
"GRPCConfigSerializer",
|
|
48
55
|
"GRPCServerInfoSerializer",
|
|
49
56
|
# Service Registry
|
|
50
|
-
"
|
|
57
|
+
"ServiceListSerializer",
|
|
51
58
|
"ServiceDetailSerializer",
|
|
52
59
|
"ServiceMethodsSerializer",
|
|
53
60
|
"MethodDetailSerializer",
|
|
@@ -64,4 +71,13 @@ __all__ = [
|
|
|
64
71
|
"ServerLifecycleChartSerializer",
|
|
65
72
|
"ErrorDistributionChartSerializer",
|
|
66
73
|
"DashboardChartsSerializer",
|
|
74
|
+
# API Keys
|
|
75
|
+
"ApiKeySerializer",
|
|
76
|
+
"ApiKeyListSerializer",
|
|
77
|
+
"ApiKeyStatsSerializer",
|
|
78
|
+
# Proto Files
|
|
79
|
+
"ProtoFileDetailSerializer",
|
|
80
|
+
"ProtoFileListSerializer",
|
|
81
|
+
"ProtoGenerateRequestSerializer",
|
|
82
|
+
"ProtoGenerateResponseSerializer",
|
|
67
83
|
]
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""
|
|
2
|
+
DRF serializers for gRPC API Keys.
|
|
3
|
+
|
|
4
|
+
Read-only serializers for listing and viewing API keys.
|
|
5
|
+
Create/Update/Delete operations handled through Django Admin.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from rest_framework import serializers
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ApiKeySerializer(serializers.Serializer):
|
|
12
|
+
"""API Key information (read-only)."""
|
|
13
|
+
|
|
14
|
+
id = serializers.IntegerField(help_text="Database ID")
|
|
15
|
+
name = serializers.CharField(help_text="Key name/description")
|
|
16
|
+
key_type = serializers.CharField(help_text="Type of API key")
|
|
17
|
+
masked_key = serializers.CharField(help_text="Masked API key (first 4 and last 4 chars)")
|
|
18
|
+
is_active = serializers.BooleanField(help_text="Whether key is active")
|
|
19
|
+
is_valid = serializers.BooleanField(help_text="Whether key is valid (active and not expired)")
|
|
20
|
+
user_id = serializers.IntegerField(help_text="User ID")
|
|
21
|
+
username = serializers.CharField(help_text="Username")
|
|
22
|
+
user_email = serializers.CharField(help_text="User email", allow_blank=True)
|
|
23
|
+
request_count = serializers.IntegerField(help_text="Total requests made with this key")
|
|
24
|
+
last_used_at = serializers.DateTimeField(
|
|
25
|
+
allow_null=True,
|
|
26
|
+
help_text="When key was last used"
|
|
27
|
+
)
|
|
28
|
+
expires_at = serializers.DateTimeField(
|
|
29
|
+
allow_null=True,
|
|
30
|
+
help_text="When key expires (null = never)"
|
|
31
|
+
)
|
|
32
|
+
created_at = serializers.DateTimeField(help_text="When key was created")
|
|
33
|
+
created_by = serializers.CharField(
|
|
34
|
+
allow_null=True,
|
|
35
|
+
help_text="User who created this key"
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class ApiKeyListSerializer(serializers.Serializer):
|
|
40
|
+
"""List of API keys response."""
|
|
41
|
+
|
|
42
|
+
results = ApiKeySerializer(many=True, help_text="List of API keys")
|
|
43
|
+
count = serializers.IntegerField(help_text="Total number of API keys")
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class ApiKeyStatsSerializer(serializers.Serializer):
|
|
47
|
+
"""API Key usage statistics."""
|
|
48
|
+
|
|
49
|
+
total_keys = serializers.IntegerField(help_text="Total API keys")
|
|
50
|
+
active_keys = serializers.IntegerField(help_text="Active API keys")
|
|
51
|
+
expired_keys = serializers.IntegerField(help_text="Expired API keys")
|
|
52
|
+
total_requests = serializers.IntegerField(help_text="Total requests across all keys")
|
|
53
|
+
keys_by_type = serializers.DictField(
|
|
54
|
+
child=serializers.IntegerField(),
|
|
55
|
+
help_text="Count of keys by type"
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
__all__ = [
|
|
60
|
+
"ApiKeySerializer",
|
|
61
|
+
"ApiKeyListSerializer",
|
|
62
|
+
"ApiKeyStatsSerializer",
|
|
63
|
+
]
|
|
@@ -1,202 +1,200 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
2
|
+
DRF serializers for gRPC charts and statistics data.
|
|
3
3
|
|
|
4
4
|
These serializers define the structure for chart endpoints
|
|
5
5
|
that provide time-series data for visualization.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
from
|
|
8
|
+
from rest_framework import serializers
|
|
9
9
|
|
|
10
|
-
from pydantic import BaseModel, Field
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
class TimeSeriesDataPoint(BaseModel):
|
|
11
|
+
class TimeSeriesDataPoint(serializers.Serializer):
|
|
14
12
|
"""Single data point in time series."""
|
|
15
13
|
|
|
16
|
-
timestamp
|
|
17
|
-
value
|
|
18
|
-
label
|
|
14
|
+
timestamp = serializers.CharField(help_text="ISO timestamp")
|
|
15
|
+
value = serializers.FloatField(help_text="Value at this timestamp")
|
|
16
|
+
label = serializers.CharField(
|
|
17
|
+
required=False, allow_null=True, help_text="Optional label for this point"
|
|
18
|
+
)
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
class ServerUptimeDataPoint(
|
|
21
|
+
class ServerUptimeDataPoint(serializers.Serializer):
|
|
22
22
|
"""Server uptime data point."""
|
|
23
23
|
|
|
24
|
-
timestamp
|
|
25
|
-
server_count
|
|
26
|
-
servers
|
|
27
|
-
|
|
24
|
+
timestamp = serializers.CharField(help_text="ISO timestamp")
|
|
25
|
+
server_count = serializers.IntegerField(help_text="Number of running servers")
|
|
26
|
+
servers = serializers.ListField(
|
|
27
|
+
child=serializers.CharField(), default=list, help_text="List of server addresses"
|
|
28
28
|
)
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
class RequestVolumeDataPoint(
|
|
31
|
+
class RequestVolumeDataPoint(serializers.Serializer):
|
|
32
32
|
"""Request volume data point."""
|
|
33
33
|
|
|
34
|
-
timestamp
|
|
35
|
-
total_requests
|
|
36
|
-
successful_requests
|
|
37
|
-
failed_requests
|
|
38
|
-
success_rate
|
|
34
|
+
timestamp = serializers.CharField(help_text="ISO timestamp")
|
|
35
|
+
total_requests = serializers.IntegerField(help_text="Total requests in period")
|
|
36
|
+
successful_requests = serializers.IntegerField(help_text="Successful requests")
|
|
37
|
+
failed_requests = serializers.IntegerField(help_text="Failed requests")
|
|
38
|
+
success_rate = serializers.FloatField(help_text="Success rate percentage")
|
|
39
39
|
|
|
40
40
|
|
|
41
|
-
class ResponseTimeDataPoint(
|
|
41
|
+
class ResponseTimeDataPoint(serializers.Serializer):
|
|
42
42
|
"""Response time statistics data point."""
|
|
43
43
|
|
|
44
|
-
timestamp
|
|
45
|
-
avg_duration_ms
|
|
46
|
-
p50_duration_ms
|
|
47
|
-
p95_duration_ms
|
|
48
|
-
p99_duration_ms
|
|
49
|
-
min_duration_ms
|
|
50
|
-
max_duration_ms
|
|
44
|
+
timestamp = serializers.CharField(help_text="ISO timestamp")
|
|
45
|
+
avg_duration_ms = serializers.FloatField(help_text="Average duration")
|
|
46
|
+
p50_duration_ms = serializers.FloatField(help_text="P50 percentile")
|
|
47
|
+
p95_duration_ms = serializers.FloatField(help_text="P95 percentile")
|
|
48
|
+
p99_duration_ms = serializers.FloatField(help_text="P99 percentile")
|
|
49
|
+
min_duration_ms = serializers.FloatField(help_text="Minimum duration")
|
|
50
|
+
max_duration_ms = serializers.FloatField(help_text="Maximum duration")
|
|
51
51
|
|
|
52
52
|
|
|
53
|
-
class ServiceActivityDataPoint(
|
|
53
|
+
class ServiceActivityDataPoint(serializers.Serializer):
|
|
54
54
|
"""Service activity data point."""
|
|
55
55
|
|
|
56
|
-
service_name
|
|
57
|
-
request_count
|
|
58
|
-
success_rate
|
|
59
|
-
avg_duration_ms
|
|
56
|
+
service_name = serializers.CharField(help_text="Service name")
|
|
57
|
+
request_count = serializers.IntegerField(help_text="Number of requests")
|
|
58
|
+
success_rate = serializers.FloatField(help_text="Success rate percentage")
|
|
59
|
+
avg_duration_ms = serializers.FloatField(help_text="Average duration")
|
|
60
60
|
|
|
61
61
|
|
|
62
|
-
class ServerLifecycleEvent(
|
|
62
|
+
class ServerLifecycleEvent(serializers.Serializer):
|
|
63
63
|
"""Server lifecycle event."""
|
|
64
64
|
|
|
65
|
-
timestamp
|
|
66
|
-
event_type
|
|
67
|
-
|
|
65
|
+
timestamp = serializers.CharField(help_text="Event timestamp")
|
|
66
|
+
event_type = serializers.CharField(
|
|
67
|
+
help_text="Event type (started, stopped, error)"
|
|
68
|
+
)
|
|
69
|
+
server_address = serializers.CharField(help_text="Server address")
|
|
70
|
+
server_pid = serializers.IntegerField(help_text="Server process ID")
|
|
71
|
+
uptime_seconds = serializers.IntegerField(
|
|
72
|
+
required=False,
|
|
73
|
+
allow_null=True,
|
|
74
|
+
help_text="Uptime at event time (for stop events)",
|
|
68
75
|
)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
uptime_seconds: Optional[int] = Field(
|
|
72
|
-
None, description="Uptime at event time (for stop events)"
|
|
76
|
+
error_message = serializers.CharField(
|
|
77
|
+
required=False, allow_null=True, help_text="Error message if applicable"
|
|
73
78
|
)
|
|
74
|
-
error_message: Optional[str] = Field(None, description="Error message if applicable")
|
|
75
79
|
|
|
76
80
|
|
|
77
|
-
class TimeSeriesChartData(
|
|
81
|
+
class TimeSeriesChartData(serializers.Serializer):
|
|
78
82
|
"""Generic time series chart data."""
|
|
79
83
|
|
|
80
|
-
title
|
|
81
|
-
series_name
|
|
82
|
-
data_points
|
|
83
|
-
|
|
84
|
-
)
|
|
85
|
-
period_hours: int = Field(..., description="Period in hours")
|
|
86
|
-
granularity: str = Field(
|
|
87
|
-
..., description="Data granularity (hour, day, week)"
|
|
88
|
-
)
|
|
84
|
+
title = serializers.CharField(help_text="Chart title")
|
|
85
|
+
series_name = serializers.CharField(help_text="Series name")
|
|
86
|
+
data_points = TimeSeriesDataPoint(many=True, default=list, help_text="Data points")
|
|
87
|
+
period_hours = serializers.IntegerField(help_text="Period in hours")
|
|
88
|
+
granularity = serializers.CharField(help_text="Data granularity (hour, day, week)")
|
|
89
89
|
|
|
90
90
|
|
|
91
|
-
class ServerUptimeChartSerializer(
|
|
91
|
+
class ServerUptimeChartSerializer(serializers.Serializer):
|
|
92
92
|
"""Server uptime over time chart data."""
|
|
93
93
|
|
|
94
|
-
title
|
|
95
|
-
data_points
|
|
96
|
-
|
|
94
|
+
title = serializers.CharField(default="Server Uptime", help_text="Chart title")
|
|
95
|
+
data_points = ServerUptimeDataPoint(
|
|
96
|
+
many=True, default=list, help_text="Uptime data points"
|
|
97
97
|
)
|
|
98
|
-
period_hours
|
|
99
|
-
granularity
|
|
100
|
-
total_servers
|
|
101
|
-
|
|
98
|
+
period_hours = serializers.IntegerField(help_text="Period in hours")
|
|
99
|
+
granularity = serializers.CharField(help_text="Data granularity")
|
|
100
|
+
total_servers = serializers.IntegerField(
|
|
101
|
+
help_text="Total unique servers in period"
|
|
102
|
+
)
|
|
103
|
+
currently_running = serializers.IntegerField(help_text="Currently running servers")
|
|
102
104
|
|
|
103
105
|
|
|
104
|
-
class RequestVolumeChartSerializer(
|
|
106
|
+
class RequestVolumeChartSerializer(serializers.Serializer):
|
|
105
107
|
"""Request volume over time chart data."""
|
|
106
108
|
|
|
107
|
-
title
|
|
108
|
-
data_points
|
|
109
|
-
|
|
109
|
+
title = serializers.CharField(default="Request Volume", help_text="Chart title")
|
|
110
|
+
data_points = RequestVolumeDataPoint(
|
|
111
|
+
many=True, default=list, help_text="Volume data points"
|
|
110
112
|
)
|
|
111
|
-
period_hours
|
|
112
|
-
granularity
|
|
113
|
-
total_requests
|
|
114
|
-
avg_success_rate
|
|
113
|
+
period_hours = serializers.IntegerField(help_text="Period in hours")
|
|
114
|
+
granularity = serializers.CharField(help_text="Data granularity")
|
|
115
|
+
total_requests = serializers.IntegerField(help_text="Total requests in period")
|
|
116
|
+
avg_success_rate = serializers.FloatField(help_text="Average success rate")
|
|
115
117
|
|
|
116
118
|
|
|
117
|
-
class ResponseTimeChartSerializer(
|
|
119
|
+
class ResponseTimeChartSerializer(serializers.Serializer):
|
|
118
120
|
"""Response time over time chart data."""
|
|
119
121
|
|
|
120
|
-
title
|
|
121
|
-
data_points
|
|
122
|
-
|
|
122
|
+
title = serializers.CharField(default="Response Time", help_text="Chart title")
|
|
123
|
+
data_points = ResponseTimeDataPoint(
|
|
124
|
+
many=True, default=list, help_text="Response time data points"
|
|
123
125
|
)
|
|
124
|
-
period_hours
|
|
125
|
-
granularity
|
|
126
|
-
overall_avg_ms
|
|
127
|
-
overall_p95_ms
|
|
126
|
+
period_hours = serializers.IntegerField(help_text="Period in hours")
|
|
127
|
+
granularity = serializers.CharField(help_text="Data granularity")
|
|
128
|
+
overall_avg_ms = serializers.FloatField(help_text="Overall average duration")
|
|
129
|
+
overall_p95_ms = serializers.FloatField(help_text="Overall P95 duration")
|
|
128
130
|
|
|
129
131
|
|
|
130
|
-
class ServiceActivityChartSerializer(
|
|
132
|
+
class ServiceActivityChartSerializer(serializers.Serializer):
|
|
131
133
|
"""Service activity comparison chart data."""
|
|
132
134
|
|
|
133
|
-
title
|
|
134
|
-
services
|
|
135
|
-
|
|
135
|
+
title = serializers.CharField(default="Service Activity", help_text="Chart title")
|
|
136
|
+
services = ServiceActivityDataPoint(
|
|
137
|
+
many=True, default=list, help_text="Service activity data"
|
|
136
138
|
)
|
|
137
|
-
period_hours
|
|
138
|
-
total_services
|
|
139
|
-
most_active_service
|
|
140
|
-
|
|
139
|
+
period_hours = serializers.IntegerField(help_text="Period in hours")
|
|
140
|
+
total_services = serializers.IntegerField(help_text="Total number of services")
|
|
141
|
+
most_active_service = serializers.CharField(
|
|
142
|
+
required=False, allow_null=True, help_text="Most active service name"
|
|
141
143
|
)
|
|
142
144
|
|
|
143
145
|
|
|
144
|
-
class ServerLifecycleChartSerializer(
|
|
146
|
+
class ServerLifecycleChartSerializer(serializers.Serializer):
|
|
145
147
|
"""Server lifecycle events timeline."""
|
|
146
148
|
|
|
147
|
-
title
|
|
148
|
-
events
|
|
149
|
-
|
|
149
|
+
title = serializers.CharField(default="Server Lifecycle", help_text="Chart title")
|
|
150
|
+
events = ServerLifecycleEvent(
|
|
151
|
+
many=True, default=list, help_text="Lifecycle events"
|
|
150
152
|
)
|
|
151
|
-
period_hours
|
|
152
|
-
total_events
|
|
153
|
-
restart_count
|
|
154
|
-
error_count
|
|
153
|
+
period_hours = serializers.IntegerField(help_text="Period in hours")
|
|
154
|
+
total_events = serializers.IntegerField(help_text="Total number of events")
|
|
155
|
+
restart_count = serializers.IntegerField(help_text="Number of server restarts")
|
|
156
|
+
error_count = serializers.IntegerField(help_text="Number of error events")
|
|
155
157
|
|
|
156
158
|
|
|
157
|
-
class ErrorDistributionDataPoint(
|
|
159
|
+
class ErrorDistributionDataPoint(serializers.Serializer):
|
|
158
160
|
"""Error distribution data point."""
|
|
159
161
|
|
|
160
|
-
error_code
|
|
161
|
-
count
|
|
162
|
-
percentage
|
|
163
|
-
service_name
|
|
162
|
+
error_code = serializers.CharField(help_text="gRPC status code")
|
|
163
|
+
count = serializers.IntegerField(help_text="Number of occurrences")
|
|
164
|
+
percentage = serializers.FloatField(help_text="Percentage of total errors")
|
|
165
|
+
service_name = serializers.CharField(
|
|
166
|
+
required=False, allow_null=True, help_text="Service name if filtered"
|
|
167
|
+
)
|
|
164
168
|
|
|
165
169
|
|
|
166
|
-
class ErrorDistributionChartSerializer(
|
|
170
|
+
class ErrorDistributionChartSerializer(serializers.Serializer):
|
|
167
171
|
"""Error distribution chart data."""
|
|
168
172
|
|
|
169
|
-
title
|
|
170
|
-
error_types
|
|
171
|
-
|
|
173
|
+
title = serializers.CharField(default="Error Distribution", help_text="Chart title")
|
|
174
|
+
error_types = ErrorDistributionDataPoint(
|
|
175
|
+
many=True, default=list, help_text="Error distribution data"
|
|
172
176
|
)
|
|
173
|
-
period_hours
|
|
174
|
-
total_errors
|
|
175
|
-
most_common_error
|
|
176
|
-
|
|
177
|
+
period_hours = serializers.IntegerField(help_text="Period in hours")
|
|
178
|
+
total_errors = serializers.IntegerField(help_text="Total number of errors")
|
|
179
|
+
most_common_error = serializers.CharField(
|
|
180
|
+
required=False, allow_null=True, help_text="Most common error code"
|
|
177
181
|
)
|
|
178
182
|
|
|
179
183
|
|
|
180
|
-
class DashboardChartsSerializer(
|
|
184
|
+
class DashboardChartsSerializer(serializers.Serializer):
|
|
181
185
|
"""Combined dashboard charts data."""
|
|
182
186
|
|
|
183
|
-
server_uptime
|
|
184
|
-
|
|
185
|
-
)
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
response_time: ResponseTimeChartSerializer = Field(
|
|
190
|
-
..., description="Response time chart"
|
|
191
|
-
)
|
|
192
|
-
service_activity: ServiceActivityChartSerializer = Field(
|
|
193
|
-
..., description="Service activity chart"
|
|
187
|
+
server_uptime = ServerUptimeChartSerializer(help_text="Server uptime chart")
|
|
188
|
+
request_volume = RequestVolumeChartSerializer(help_text="Request volume chart")
|
|
189
|
+
response_time = ResponseTimeChartSerializer(help_text="Response time chart")
|
|
190
|
+
service_activity = ServiceActivityChartSerializer(help_text="Service activity chart")
|
|
191
|
+
error_distribution = ErrorDistributionChartSerializer(
|
|
192
|
+
help_text="Error distribution chart"
|
|
194
193
|
)
|
|
195
|
-
|
|
196
|
-
|
|
194
|
+
period_hours = serializers.IntegerField(
|
|
195
|
+
help_text="Period in hours for all charts"
|
|
197
196
|
)
|
|
198
|
-
|
|
199
|
-
generated_at: str = Field(..., description="When data was generated")
|
|
197
|
+
generated_at = serializers.CharField(help_text="When data was generated")
|
|
200
198
|
|
|
201
199
|
|
|
202
200
|
__all__ = [
|