django-cfg 1.4.62__py3-none-any.whl → 1.4.64__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/accounts/services/otp_service.py +3 -14
- django_cfg/apps/centrifugo/__init__.py +57 -0
- django_cfg/apps/centrifugo/admin/__init__.py +13 -0
- django_cfg/apps/centrifugo/admin/centrifugo_log.py +249 -0
- django_cfg/apps/centrifugo/admin/config.py +82 -0
- django_cfg/apps/centrifugo/apps.py +31 -0
- django_cfg/apps/centrifugo/codegen/IMPLEMENTATION_SUMMARY.md +475 -0
- django_cfg/apps/centrifugo/codegen/README.md +242 -0
- django_cfg/apps/centrifugo/codegen/USAGE.md +616 -0
- django_cfg/apps/centrifugo/codegen/__init__.py +19 -0
- django_cfg/apps/centrifugo/codegen/discovery.py +246 -0
- django_cfg/apps/centrifugo/codegen/generators/go_thin/__init__.py +5 -0
- django_cfg/apps/centrifugo/codegen/generators/go_thin/generator.py +174 -0
- django_cfg/apps/centrifugo/codegen/generators/go_thin/templates/README.md.j2 +182 -0
- django_cfg/apps/centrifugo/codegen/generators/go_thin/templates/client.go.j2 +64 -0
- django_cfg/apps/centrifugo/codegen/generators/go_thin/templates/go.mod.j2 +10 -0
- django_cfg/apps/centrifugo/codegen/generators/go_thin/templates/rpc_client.go.j2 +300 -0
- django_cfg/apps/centrifugo/codegen/generators/go_thin/templates/rpc_client.go.j2.old +267 -0
- django_cfg/apps/centrifugo/codegen/generators/go_thin/templates/types.go.j2 +16 -0
- django_cfg/apps/centrifugo/codegen/generators/python_thin/__init__.py +7 -0
- django_cfg/apps/centrifugo/codegen/generators/python_thin/generator.py +241 -0
- django_cfg/apps/centrifugo/codegen/generators/python_thin/templates/README.md.j2 +128 -0
- django_cfg/apps/centrifugo/codegen/generators/python_thin/templates/__init__.py.j2 +22 -0
- django_cfg/apps/centrifugo/codegen/generators/python_thin/templates/client.py.j2 +73 -0
- django_cfg/apps/centrifugo/codegen/generators/python_thin/templates/models.py.j2 +19 -0
- django_cfg/apps/centrifugo/codegen/generators/python_thin/templates/requirements.txt.j2 +8 -0
- django_cfg/apps/centrifugo/codegen/generators/python_thin/templates/rpc_client.py.j2 +193 -0
- django_cfg/apps/centrifugo/codegen/generators/typescript_thin/__init__.py +5 -0
- django_cfg/apps/centrifugo/codegen/generators/typescript_thin/generator.py +124 -0
- django_cfg/apps/centrifugo/codegen/generators/typescript_thin/templates/README.md.j2 +38 -0
- django_cfg/apps/centrifugo/codegen/generators/typescript_thin/templates/client.ts.j2 +25 -0
- django_cfg/apps/centrifugo/codegen/generators/typescript_thin/templates/index.ts.j2 +12 -0
- django_cfg/apps/centrifugo/codegen/generators/typescript_thin/templates/package.json.j2 +13 -0
- django_cfg/apps/centrifugo/codegen/generators/typescript_thin/templates/rpc-client.ts.j2 +137 -0
- django_cfg/apps/centrifugo/codegen/generators/typescript_thin/templates/tsconfig.json.j2 +14 -0
- django_cfg/apps/centrifugo/codegen/generators/typescript_thin/templates/types.ts.j2 +9 -0
- django_cfg/apps/centrifugo/codegen/utils/__init__.py +37 -0
- django_cfg/apps/centrifugo/codegen/utils/naming.py +155 -0
- django_cfg/apps/centrifugo/codegen/utils/type_converter.py +349 -0
- django_cfg/apps/centrifugo/decorators.py +137 -0
- django_cfg/apps/centrifugo/management/__init__.py +1 -0
- django_cfg/apps/centrifugo/management/commands/__init__.py +1 -0
- django_cfg/apps/centrifugo/management/commands/generate_centrifugo_clients.py +254 -0
- django_cfg/apps/centrifugo/managers/__init__.py +12 -0
- django_cfg/apps/centrifugo/managers/centrifugo_log.py +264 -0
- django_cfg/apps/centrifugo/migrations/0001_initial.py +164 -0
- django_cfg/apps/centrifugo/migrations/__init__.py +3 -0
- django_cfg/apps/centrifugo/models/__init__.py +11 -0
- django_cfg/apps/centrifugo/models/centrifugo_log.py +210 -0
- django_cfg/apps/centrifugo/registry.py +106 -0
- django_cfg/apps/centrifugo/router.py +125 -0
- django_cfg/apps/centrifugo/serializers/__init__.py +40 -0
- django_cfg/apps/centrifugo/serializers/admin_api.py +264 -0
- django_cfg/apps/centrifugo/serializers/channels.py +26 -0
- django_cfg/apps/centrifugo/serializers/health.py +17 -0
- django_cfg/apps/centrifugo/serializers/publishes.py +16 -0
- django_cfg/apps/centrifugo/serializers/stats.py +21 -0
- django_cfg/apps/centrifugo/services/__init__.py +12 -0
- django_cfg/apps/centrifugo/services/client/__init__.py +29 -0
- django_cfg/apps/centrifugo/services/client/client.py +582 -0
- django_cfg/apps/centrifugo/services/client/config.py +236 -0
- django_cfg/apps/centrifugo/services/client/exceptions.py +212 -0
- django_cfg/apps/centrifugo/services/config_helper.py +63 -0
- django_cfg/apps/centrifugo/services/dashboard_notifier.py +157 -0
- django_cfg/apps/centrifugo/services/logging.py +677 -0
- django_cfg/apps/centrifugo/static/django_cfg_centrifugo/css/dashboard.css +260 -0
- django_cfg/apps/centrifugo/static/django_cfg_centrifugo/js/dashboard/live_channels.mjs +313 -0
- django_cfg/apps/centrifugo/static/django_cfg_centrifugo/js/dashboard/live_testing.mjs +803 -0
- django_cfg/apps/centrifugo/static/django_cfg_centrifugo/js/dashboard/main.mjs +333 -0
- django_cfg/apps/centrifugo/static/django_cfg_centrifugo/js/dashboard/overview.mjs +432 -0
- django_cfg/apps/centrifugo/static/django_cfg_centrifugo/js/dashboard/testing.mjs +33 -0
- django_cfg/apps/centrifugo/static/django_cfg_centrifugo/js/dashboard/websocket.mjs +210 -0
- django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/components/channels_content.html +46 -0
- django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/components/live_channels_content.html +123 -0
- django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/components/overview_content.html +45 -0
- django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/components/publishes_content.html +84 -0
- django_cfg/apps/{ipc/templates/django_cfg_ipc → centrifugo/templates/django_cfg_centrifugo}/components/stat_cards.html +23 -20
- django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/components/system_status.html +91 -0
- django_cfg/apps/{ipc/templates/django_cfg_ipc → centrifugo/templates/django_cfg_centrifugo}/components/tab_navigation.html +15 -15
- django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/components/testing_tools.html +415 -0
- django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/layout/base.html +61 -0
- django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/pages/dashboard.html +58 -0
- django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/tags/connection_script.html +48 -0
- django_cfg/apps/centrifugo/templatetags/__init__.py +1 -0
- django_cfg/apps/centrifugo/templatetags/centrifugo_tags.py +81 -0
- django_cfg/apps/centrifugo/urls.py +31 -0
- django_cfg/apps/{ipc → centrifugo}/urls_admin.py +4 -4
- django_cfg/apps/centrifugo/views/__init__.py +15 -0
- django_cfg/apps/centrifugo/views/admin_api.py +380 -0
- django_cfg/apps/centrifugo/views/dashboard.py +15 -0
- django_cfg/apps/centrifugo/views/monitoring.py +286 -0
- django_cfg/apps/centrifugo/views/testing_api.py +422 -0
- django_cfg/apps/support/utils/support_email_service.py +5 -18
- django_cfg/apps/tasks/templates/tasks/layout/base.html +0 -2
- django_cfg/apps/urls.py +5 -5
- django_cfg/core/base/config_model.py +4 -44
- django_cfg/core/builders/apps_builder.py +2 -2
- django_cfg/core/generation/integration_generators/third_party.py +8 -8
- django_cfg/core/utils/__init__.py +5 -0
- django_cfg/core/utils/url_helpers.py +73 -0
- django_cfg/modules/base.py +7 -7
- django_cfg/modules/django_client/core/__init__.py +2 -1
- django_cfg/modules/django_client/core/config/config.py +8 -0
- django_cfg/modules/django_client/core/generator/__init__.py +42 -2
- django_cfg/modules/django_client/core/generator/go/__init__.py +14 -0
- django_cfg/modules/django_client/core/generator/go/client_generator.py +124 -0
- django_cfg/modules/django_client/core/generator/go/files_generator.py +133 -0
- django_cfg/modules/django_client/core/generator/go/generator.py +203 -0
- django_cfg/modules/django_client/core/generator/go/models_generator.py +304 -0
- django_cfg/modules/django_client/core/generator/go/naming.py +193 -0
- django_cfg/modules/django_client/core/generator/go/operations_generator.py +134 -0
- django_cfg/modules/django_client/core/generator/go/templates/Makefile.j2 +38 -0
- django_cfg/modules/django_client/core/generator/go/templates/README.md.j2 +55 -0
- django_cfg/modules/django_client/core/generator/go/templates/client.go.j2 +122 -0
- django_cfg/modules/django_client/core/generator/go/templates/enums.go.j2 +49 -0
- django_cfg/modules/django_client/core/generator/go/templates/errors.go.j2 +182 -0
- django_cfg/modules/django_client/core/generator/go/templates/go.mod.j2 +6 -0
- django_cfg/modules/django_client/core/generator/go/templates/main_client.go.j2 +60 -0
- django_cfg/modules/django_client/core/generator/go/templates/middleware.go.j2 +388 -0
- django_cfg/modules/django_client/core/generator/go/templates/models.go.j2 +28 -0
- django_cfg/modules/django_client/core/generator/go/templates/operations_client.go.j2 +142 -0
- django_cfg/modules/django_client/core/generator/go/templates/validation.go.j2 +217 -0
- django_cfg/modules/django_client/core/generator/go/type_mapper.py +380 -0
- django_cfg/modules/django_client/management/commands/generate_client.py +53 -3
- django_cfg/modules/django_client/system/generate_mjs_clients.py +3 -1
- django_cfg/modules/django_client/system/schema_parser.py +5 -1
- django_cfg/modules/django_tailwind/templates/django_tailwind/base.html +1 -0
- django_cfg/modules/django_twilio/sendgrid_service.py +7 -4
- django_cfg/modules/django_unfold/dashboard.py +25 -19
- django_cfg/pyproject.toml +1 -1
- django_cfg/registry/core.py +2 -0
- django_cfg/registry/modules.py +2 -2
- django_cfg/static/js/api/centrifugo/client.mjs +164 -0
- django_cfg/static/js/api/centrifugo/index.mjs +13 -0
- django_cfg/static/js/api/index.mjs +5 -5
- django_cfg/static/js/api/types.mjs +89 -26
- {django_cfg-1.4.62.dist-info → django_cfg-1.4.64.dist-info}/METADATA +1 -1
- {django_cfg-1.4.62.dist-info → django_cfg-1.4.64.dist-info}/RECORD +142 -70
- django_cfg/apps/ipc/README.md +0 -346
- django_cfg/apps/ipc/RPC_LOGGING.md +0 -321
- django_cfg/apps/ipc/TESTING.md +0 -539
- django_cfg/apps/ipc/__init__.py +0 -60
- django_cfg/apps/ipc/admin.py +0 -232
- django_cfg/apps/ipc/apps.py +0 -98
- django_cfg/apps/ipc/migrations/0001_initial.py +0 -137
- django_cfg/apps/ipc/migrations/0002_rpclog_is_event.py +0 -23
- django_cfg/apps/ipc/migrations/__init__.py +0 -0
- django_cfg/apps/ipc/models.py +0 -229
- django_cfg/apps/ipc/serializers/__init__.py +0 -29
- django_cfg/apps/ipc/serializers/serializers.py +0 -343
- django_cfg/apps/ipc/services/__init__.py +0 -7
- django_cfg/apps/ipc/services/client/__init__.py +0 -23
- django_cfg/apps/ipc/services/client/client.py +0 -621
- django_cfg/apps/ipc/services/client/config.py +0 -214
- django_cfg/apps/ipc/services/client/exceptions.py +0 -201
- django_cfg/apps/ipc/services/logging.py +0 -239
- django_cfg/apps/ipc/services/monitor.py +0 -466
- django_cfg/apps/ipc/services/rpc_log_consumer.py +0 -330
- django_cfg/apps/ipc/static/django_cfg_ipc/js/dashboard/main.mjs +0 -269
- django_cfg/apps/ipc/static/django_cfg_ipc/js/dashboard/overview.mjs +0 -259
- django_cfg/apps/ipc/static/django_cfg_ipc/js/dashboard/testing.mjs +0 -375
- django_cfg/apps/ipc/static/django_cfg_ipc/js/dashboard.mjs.old +0 -441
- django_cfg/apps/ipc/templates/django_cfg_ipc/components/methods_content.html +0 -22
- django_cfg/apps/ipc/templates/django_cfg_ipc/components/notifications_content.html +0 -9
- django_cfg/apps/ipc/templates/django_cfg_ipc/components/overview_content.html +0 -9
- django_cfg/apps/ipc/templates/django_cfg_ipc/components/requests_content.html +0 -23
- django_cfg/apps/ipc/templates/django_cfg_ipc/components/system_status.html +0 -47
- django_cfg/apps/ipc/templates/django_cfg_ipc/components/testing_tools.html +0 -184
- django_cfg/apps/ipc/templates/django_cfg_ipc/layout/base.html +0 -71
- django_cfg/apps/ipc/templates/django_cfg_ipc/pages/dashboard.html +0 -56
- django_cfg/apps/ipc/urls.py +0 -23
- django_cfg/apps/ipc/views/__init__.py +0 -13
- django_cfg/apps/ipc/views/dashboard.py +0 -15
- django_cfg/apps/ipc/views/monitoring.py +0 -251
- django_cfg/apps/ipc/views/testing.py +0 -285
- django_cfg/static/js/api/ipc/client.mjs +0 -114
- django_cfg/static/js/api/ipc/index.mjs +0 -13
- {django_cfg-1.4.62.dist-info → django_cfg-1.4.64.dist-info}/WHEEL +0 -0
- {django_cfg-1.4.62.dist-info → django_cfg-1.4.64.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.4.62.dist-info → django_cfg-1.4.64.dist-info}/licenses/LICENSE +0 -0
django_cfg/apps/ipc/models.py
DELETED
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
IPC/RPC Models for logging and monitoring.
|
|
3
|
-
|
|
4
|
-
Models:
|
|
5
|
-
- RPCLog: Log of all RPC calls for debugging and analytics
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
import uuid
|
|
9
|
-
from django.conf import settings
|
|
10
|
-
from django.db import models
|
|
11
|
-
from django.utils import timezone
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class RPCLogManager(models.Manager):
|
|
15
|
-
"""Custom manager for RPCLog model."""
|
|
16
|
-
|
|
17
|
-
def recent(self, hours=24):
|
|
18
|
-
"""Get logs from last N hours."""
|
|
19
|
-
since = timezone.now() - timezone.timedelta(hours=hours)
|
|
20
|
-
return self.filter(created_at__gte=since)
|
|
21
|
-
|
|
22
|
-
def failed(self):
|
|
23
|
-
"""Get failed RPC calls."""
|
|
24
|
-
return self.filter(status=RPCLog.StatusChoices.FAILED)
|
|
25
|
-
|
|
26
|
-
def by_method(self, method):
|
|
27
|
-
"""Get logs for specific RPC method."""
|
|
28
|
-
return self.filter(method=method)
|
|
29
|
-
|
|
30
|
-
def stats_by_method(self):
|
|
31
|
-
"""
|
|
32
|
-
Get statistics grouped by method.
|
|
33
|
-
|
|
34
|
-
Returns:
|
|
35
|
-
QuerySet with aggregated data per method
|
|
36
|
-
"""
|
|
37
|
-
from django.db.models import Count, Avg, Max, Min
|
|
38
|
-
|
|
39
|
-
return self.values('method').annotate(
|
|
40
|
-
total_calls=Count('id'),
|
|
41
|
-
avg_duration_ms=Avg('duration_ms'),
|
|
42
|
-
max_duration_ms=Max('duration_ms'),
|
|
43
|
-
min_duration_ms=Min('duration_ms'),
|
|
44
|
-
success_count=Count('id', filter=models.Q(status='success')),
|
|
45
|
-
failed_count=Count('id', filter=models.Q(status='failed')),
|
|
46
|
-
).order_by('-total_calls')
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
class RPCLog(models.Model):
|
|
50
|
-
"""
|
|
51
|
-
Log of RPC calls between Django and WebSocket server.
|
|
52
|
-
|
|
53
|
-
Used for:
|
|
54
|
-
- Debugging RPC communication
|
|
55
|
-
- Performance monitoring
|
|
56
|
-
- Analytics (most used methods, success rate)
|
|
57
|
-
- Audit trail (who called what and when)
|
|
58
|
-
"""
|
|
59
|
-
|
|
60
|
-
class StatusChoices(models.TextChoices):
|
|
61
|
-
PENDING = 'pending', 'Pending'
|
|
62
|
-
SUCCESS = 'success', 'Success'
|
|
63
|
-
FAILED = 'failed', 'Failed'
|
|
64
|
-
TIMEOUT = 'timeout', 'Timeout'
|
|
65
|
-
|
|
66
|
-
# Primary key
|
|
67
|
-
id = models.UUIDField(
|
|
68
|
-
primary_key=True,
|
|
69
|
-
default=uuid.uuid4,
|
|
70
|
-
editable=False
|
|
71
|
-
)
|
|
72
|
-
|
|
73
|
-
# Correlation ID (matches RPC correlation_id)
|
|
74
|
-
correlation_id = models.CharField(
|
|
75
|
-
max_length=100,
|
|
76
|
-
db_index=True,
|
|
77
|
-
verbose_name="Correlation ID",
|
|
78
|
-
help_text="UUID from RPC request"
|
|
79
|
-
)
|
|
80
|
-
|
|
81
|
-
# User who initiated the call (optional)
|
|
82
|
-
user = models.ForeignKey(
|
|
83
|
-
settings.AUTH_USER_MODEL,
|
|
84
|
-
on_delete=models.SET_NULL,
|
|
85
|
-
null=True,
|
|
86
|
-
blank=True,
|
|
87
|
-
related_name='rpc_logs',
|
|
88
|
-
verbose_name="User"
|
|
89
|
-
)
|
|
90
|
-
|
|
91
|
-
# RPC method name
|
|
92
|
-
method = models.CharField(
|
|
93
|
-
max_length=100,
|
|
94
|
-
db_index=True,
|
|
95
|
-
verbose_name="RPC Method",
|
|
96
|
-
help_text="e.g., send_notification, workspace.file_changed"
|
|
97
|
-
)
|
|
98
|
-
|
|
99
|
-
# Request parameters (JSON)
|
|
100
|
-
params = models.JSONField(
|
|
101
|
-
verbose_name="Request Params",
|
|
102
|
-
help_text="Parameters sent to RPC method"
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
# Response data (JSON, nullable if failed)
|
|
106
|
-
response = models.JSONField(
|
|
107
|
-
null=True,
|
|
108
|
-
blank=True,
|
|
109
|
-
verbose_name="Response Data",
|
|
110
|
-
help_text="Result from RPC call"
|
|
111
|
-
)
|
|
112
|
-
|
|
113
|
-
# Type: RPC call or server event
|
|
114
|
-
is_event = models.BooleanField(
|
|
115
|
-
default=False,
|
|
116
|
-
db_index=True,
|
|
117
|
-
verbose_name="Is Event",
|
|
118
|
-
help_text="True if this is a server-to-client event (not a request-response RPC call)"
|
|
119
|
-
)
|
|
120
|
-
|
|
121
|
-
# Status
|
|
122
|
-
status = models.CharField(
|
|
123
|
-
max_length=20,
|
|
124
|
-
choices=StatusChoices.choices,
|
|
125
|
-
default=StatusChoices.PENDING,
|
|
126
|
-
db_index=True,
|
|
127
|
-
verbose_name="Status"
|
|
128
|
-
)
|
|
129
|
-
|
|
130
|
-
# Error details (if failed)
|
|
131
|
-
error_code = models.CharField(
|
|
132
|
-
max_length=50,
|
|
133
|
-
null=True,
|
|
134
|
-
blank=True,
|
|
135
|
-
verbose_name="Error Code"
|
|
136
|
-
)
|
|
137
|
-
error_message = models.TextField(
|
|
138
|
-
null=True,
|
|
139
|
-
blank=True,
|
|
140
|
-
verbose_name="Error Message"
|
|
141
|
-
)
|
|
142
|
-
|
|
143
|
-
# Performance metrics
|
|
144
|
-
duration_ms = models.IntegerField(
|
|
145
|
-
null=True,
|
|
146
|
-
blank=True,
|
|
147
|
-
verbose_name="Duration (ms)",
|
|
148
|
-
help_text="Time taken for RPC call in milliseconds"
|
|
149
|
-
)
|
|
150
|
-
|
|
151
|
-
# Metadata
|
|
152
|
-
caller_ip = models.GenericIPAddressField(
|
|
153
|
-
null=True,
|
|
154
|
-
blank=True,
|
|
155
|
-
verbose_name="Caller IP"
|
|
156
|
-
)
|
|
157
|
-
user_agent = models.TextField(
|
|
158
|
-
null=True,
|
|
159
|
-
blank=True,
|
|
160
|
-
verbose_name="User Agent"
|
|
161
|
-
)
|
|
162
|
-
|
|
163
|
-
# Timestamps
|
|
164
|
-
created_at = models.DateTimeField(
|
|
165
|
-
default=timezone.now,
|
|
166
|
-
db_index=True,
|
|
167
|
-
verbose_name="Created At"
|
|
168
|
-
)
|
|
169
|
-
completed_at = models.DateTimeField(
|
|
170
|
-
null=True,
|
|
171
|
-
blank=True,
|
|
172
|
-
verbose_name="Completed At"
|
|
173
|
-
)
|
|
174
|
-
|
|
175
|
-
# Custom manager
|
|
176
|
-
objects = RPCLogManager()
|
|
177
|
-
|
|
178
|
-
class Meta:
|
|
179
|
-
app_label = 'django_cfg_ipc'
|
|
180
|
-
verbose_name = "RPC Log"
|
|
181
|
-
verbose_name_plural = "RPC Logs"
|
|
182
|
-
ordering = ['-created_at']
|
|
183
|
-
indexes = [
|
|
184
|
-
models.Index(fields=['method', 'status']),
|
|
185
|
-
models.Index(fields=['status', 'created_at']),
|
|
186
|
-
models.Index(fields=['correlation_id']),
|
|
187
|
-
models.Index(fields=['user', 'created_at']),
|
|
188
|
-
]
|
|
189
|
-
|
|
190
|
-
def __str__(self):
|
|
191
|
-
return f"{self.method} ({self.status}) - {self.created_at.strftime('%Y-%m-%d %H:%M:%S')}"
|
|
192
|
-
|
|
193
|
-
@property
|
|
194
|
-
def is_successful(self):
|
|
195
|
-
"""Check if RPC call was successful."""
|
|
196
|
-
return self.status == self.StatusChoices.SUCCESS
|
|
197
|
-
|
|
198
|
-
@property
|
|
199
|
-
def is_failed(self):
|
|
200
|
-
"""Check if RPC call failed."""
|
|
201
|
-
return self.status in [self.StatusChoices.FAILED, self.StatusChoices.TIMEOUT]
|
|
202
|
-
|
|
203
|
-
def mark_success(self, response_data, duration_ms=None):
|
|
204
|
-
"""Mark RPC call as successful."""
|
|
205
|
-
self.status = self.StatusChoices.SUCCESS
|
|
206
|
-
self.response = response_data
|
|
207
|
-
self.completed_at = timezone.now()
|
|
208
|
-
if duration_ms is not None:
|
|
209
|
-
self.duration_ms = duration_ms
|
|
210
|
-
self.save()
|
|
211
|
-
|
|
212
|
-
def mark_failed(self, error_code, error_message, duration_ms=None):
|
|
213
|
-
"""Mark RPC call as failed."""
|
|
214
|
-
self.status = self.StatusChoices.FAILED
|
|
215
|
-
self.error_code = error_code
|
|
216
|
-
self.error_message = error_message
|
|
217
|
-
self.completed_at = timezone.now()
|
|
218
|
-
if duration_ms is not None:
|
|
219
|
-
self.duration_ms = duration_ms
|
|
220
|
-
self.save()
|
|
221
|
-
|
|
222
|
-
def mark_timeout(self, timeout_seconds):
|
|
223
|
-
"""Mark RPC call as timed out."""
|
|
224
|
-
self.status = self.StatusChoices.TIMEOUT
|
|
225
|
-
self.error_code = 'timeout'
|
|
226
|
-
self.error_message = f'RPC call timed out after {timeout_seconds}s'
|
|
227
|
-
self.completed_at = timezone.now()
|
|
228
|
-
self.duration_ms = timeout_seconds * 1000
|
|
229
|
-
self.save()
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Serializers for IPC/RPC module.
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
from .serializers import (
|
|
6
|
-
HealthCheckSerializer,
|
|
7
|
-
LoadTestRequestSerializer,
|
|
8
|
-
LoadTestResponseSerializer,
|
|
9
|
-
LoadTestStatusSerializer,
|
|
10
|
-
MethodStatsSerializer,
|
|
11
|
-
NotificationStatsSerializer,
|
|
12
|
-
OverviewStatsSerializer,
|
|
13
|
-
RecentRequestsSerializer,
|
|
14
|
-
TestRPCRequestSerializer,
|
|
15
|
-
TestRPCResponseSerializer,
|
|
16
|
-
)
|
|
17
|
-
|
|
18
|
-
__all__ = [
|
|
19
|
-
'HealthCheckSerializer',
|
|
20
|
-
'OverviewStatsSerializer',
|
|
21
|
-
'RecentRequestsSerializer',
|
|
22
|
-
'NotificationStatsSerializer',
|
|
23
|
-
'MethodStatsSerializer',
|
|
24
|
-
'TestRPCRequestSerializer',
|
|
25
|
-
'TestRPCResponseSerializer',
|
|
26
|
-
'LoadTestRequestSerializer',
|
|
27
|
-
'LoadTestResponseSerializer',
|
|
28
|
-
'LoadTestStatusSerializer',
|
|
29
|
-
]
|
|
@@ -1,343 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Serializers for RPC Dashboard API.
|
|
3
|
-
|
|
4
|
-
DRF serializers for consistent API responses with type hints.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
from rest_framework import serializers
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class HealthCheckSerializer(serializers.Serializer):
|
|
12
|
-
"""Serializer for health check response."""
|
|
13
|
-
|
|
14
|
-
redis_connected = serializers.BooleanField(
|
|
15
|
-
help_text="Whether Redis is connected"
|
|
16
|
-
)
|
|
17
|
-
stream_exists = serializers.BooleanField(
|
|
18
|
-
help_text="Whether the request stream exists"
|
|
19
|
-
)
|
|
20
|
-
stream_length = serializers.IntegerField(
|
|
21
|
-
help_text="Number of entries in the stream"
|
|
22
|
-
)
|
|
23
|
-
consumer_group_exists = serializers.BooleanField(
|
|
24
|
-
required=False,
|
|
25
|
-
default=False,
|
|
26
|
-
help_text="Whether the consumer group exists"
|
|
27
|
-
)
|
|
28
|
-
recent_activity = serializers.BooleanField(
|
|
29
|
-
help_text="Whether there was recent activity (last 5 min)"
|
|
30
|
-
)
|
|
31
|
-
last_request_time = serializers.CharField(
|
|
32
|
-
required=False,
|
|
33
|
-
allow_null=True,
|
|
34
|
-
default=None,
|
|
35
|
-
help_text="ISO timestamp of last request"
|
|
36
|
-
)
|
|
37
|
-
error = serializers.CharField(
|
|
38
|
-
required=False,
|
|
39
|
-
allow_null=True,
|
|
40
|
-
help_text="Error message if any"
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
class OverviewStatsSerializer(serializers.Serializer):
|
|
45
|
-
"""Serializer for overview statistics."""
|
|
46
|
-
|
|
47
|
-
redis_connected = serializers.BooleanField(
|
|
48
|
-
required=False,
|
|
49
|
-
help_text="Whether Redis is connected"
|
|
50
|
-
)
|
|
51
|
-
total_requests_today = serializers.IntegerField(
|
|
52
|
-
help_text="Total requests processed today"
|
|
53
|
-
)
|
|
54
|
-
total_requests_hour = serializers.IntegerField(
|
|
55
|
-
required=False,
|
|
56
|
-
default=0,
|
|
57
|
-
help_text="Total requests in the last hour"
|
|
58
|
-
)
|
|
59
|
-
active_methods = serializers.ListField(
|
|
60
|
-
child=serializers.CharField(),
|
|
61
|
-
help_text="List of active RPC methods"
|
|
62
|
-
)
|
|
63
|
-
top_method = serializers.CharField(
|
|
64
|
-
required=False,
|
|
65
|
-
allow_null=True,
|
|
66
|
-
help_text="Most frequently called method"
|
|
67
|
-
)
|
|
68
|
-
method_counts = serializers.DictField(
|
|
69
|
-
required=False,
|
|
70
|
-
help_text="Count of requests per method"
|
|
71
|
-
)
|
|
72
|
-
avg_response_time_ms = serializers.FloatField(
|
|
73
|
-
help_text="Average response time in milliseconds"
|
|
74
|
-
)
|
|
75
|
-
success_rate = serializers.FloatField(
|
|
76
|
-
help_text="Success rate percentage"
|
|
77
|
-
)
|
|
78
|
-
error_rate = serializers.FloatField(
|
|
79
|
-
required=False,
|
|
80
|
-
default=0.0,
|
|
81
|
-
help_text="Error rate percentage"
|
|
82
|
-
)
|
|
83
|
-
timestamp = serializers.CharField(
|
|
84
|
-
required=False,
|
|
85
|
-
help_text="ISO timestamp of the stats"
|
|
86
|
-
)
|
|
87
|
-
error = serializers.CharField(
|
|
88
|
-
required=False,
|
|
89
|
-
allow_null=True,
|
|
90
|
-
help_text="Error message if any"
|
|
91
|
-
)
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
class RPCRequestSerializer(serializers.Serializer):
|
|
95
|
-
"""Serializer for individual RPC request."""
|
|
96
|
-
|
|
97
|
-
id = serializers.CharField(
|
|
98
|
-
required=False,
|
|
99
|
-
help_text="Stream entry ID"
|
|
100
|
-
)
|
|
101
|
-
request_id = serializers.CharField(
|
|
102
|
-
required=False,
|
|
103
|
-
help_text="Unique request ID"
|
|
104
|
-
)
|
|
105
|
-
timestamp = serializers.CharField(
|
|
106
|
-
help_text="ISO timestamp of the request"
|
|
107
|
-
)
|
|
108
|
-
method = serializers.CharField(
|
|
109
|
-
allow_null=True,
|
|
110
|
-
help_text="RPC method name"
|
|
111
|
-
)
|
|
112
|
-
params = serializers.DictField(
|
|
113
|
-
allow_null=True,
|
|
114
|
-
required=False,
|
|
115
|
-
help_text="Request parameters"
|
|
116
|
-
)
|
|
117
|
-
correlation_id = serializers.CharField(
|
|
118
|
-
allow_null=True,
|
|
119
|
-
required=False,
|
|
120
|
-
help_text="Correlation ID for tracking"
|
|
121
|
-
)
|
|
122
|
-
source = serializers.CharField(
|
|
123
|
-
allow_null=True,
|
|
124
|
-
required=False,
|
|
125
|
-
help_text="Source of the request"
|
|
126
|
-
)
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
class RecentRequestsSerializer(serializers.Serializer):
|
|
130
|
-
"""Serializer for recent requests response."""
|
|
131
|
-
|
|
132
|
-
requests = serializers.ListField(
|
|
133
|
-
child=RPCRequestSerializer(),
|
|
134
|
-
help_text="List of recent RPC requests"
|
|
135
|
-
)
|
|
136
|
-
count = serializers.IntegerField(
|
|
137
|
-
help_text="Number of requests returned"
|
|
138
|
-
)
|
|
139
|
-
total_available = serializers.IntegerField(
|
|
140
|
-
help_text="Total number of requests available"
|
|
141
|
-
)
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
class NotificationTypeStatsSerializer(serializers.Serializer):
|
|
145
|
-
"""Serializer for notification type statistics."""
|
|
146
|
-
|
|
147
|
-
user_activity = serializers.IntegerField(default=0)
|
|
148
|
-
system_alert = serializers.IntegerField(default=0)
|
|
149
|
-
error_notification = serializers.IntegerField(default=0)
|
|
150
|
-
info_message = serializers.IntegerField(default=0)
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
class NotificationStatsSerializer(serializers.Serializer):
|
|
154
|
-
"""Serializer for notification statistics."""
|
|
155
|
-
|
|
156
|
-
total_sent = serializers.IntegerField(
|
|
157
|
-
help_text="Total notifications sent"
|
|
158
|
-
)
|
|
159
|
-
delivery_rate = serializers.FloatField(
|
|
160
|
-
help_text="Delivery success rate percentage"
|
|
161
|
-
)
|
|
162
|
-
by_type = serializers.DictField(
|
|
163
|
-
required=False,
|
|
164
|
-
help_text="Breakdown by notification type"
|
|
165
|
-
)
|
|
166
|
-
recent = serializers.ListField(
|
|
167
|
-
required=False,
|
|
168
|
-
help_text="Recent notifications"
|
|
169
|
-
)
|
|
170
|
-
last_sent = serializers.CharField(
|
|
171
|
-
allow_null=True,
|
|
172
|
-
required=False,
|
|
173
|
-
help_text="ISO timestamp of last notification"
|
|
174
|
-
)
|
|
175
|
-
timestamp = serializers.CharField(
|
|
176
|
-
required=False,
|
|
177
|
-
help_text="ISO timestamp of the stats"
|
|
178
|
-
)
|
|
179
|
-
error = serializers.CharField(
|
|
180
|
-
required=False,
|
|
181
|
-
allow_null=True,
|
|
182
|
-
help_text="Error message if any"
|
|
183
|
-
)
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
class MethodStatSerializer(serializers.Serializer):
|
|
187
|
-
"""Serializer for individual method statistics."""
|
|
188
|
-
|
|
189
|
-
method = serializers.CharField(
|
|
190
|
-
help_text="RPC method name"
|
|
191
|
-
)
|
|
192
|
-
count = serializers.IntegerField(
|
|
193
|
-
help_text="Number of calls"
|
|
194
|
-
)
|
|
195
|
-
percentage = serializers.FloatField(
|
|
196
|
-
help_text="Percentage of total calls"
|
|
197
|
-
)
|
|
198
|
-
avg_time_ms = serializers.FloatField(
|
|
199
|
-
required=False,
|
|
200
|
-
help_text="Average execution time in milliseconds"
|
|
201
|
-
)
|
|
202
|
-
avg_time = serializers.FloatField(
|
|
203
|
-
required=False,
|
|
204
|
-
help_text="Average execution time (alternative field)"
|
|
205
|
-
)
|
|
206
|
-
success_rate = serializers.FloatField(
|
|
207
|
-
required=False,
|
|
208
|
-
default=100.0,
|
|
209
|
-
help_text="Success rate percentage"
|
|
210
|
-
)
|
|
211
|
-
last_called = serializers.CharField(
|
|
212
|
-
allow_null=True,
|
|
213
|
-
required=False,
|
|
214
|
-
help_text="ISO timestamp of last call"
|
|
215
|
-
)
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
class MethodStatsSerializer(serializers.Serializer):
|
|
219
|
-
"""Serializer for method statistics response."""
|
|
220
|
-
|
|
221
|
-
methods = serializers.ListField(
|
|
222
|
-
child=MethodStatSerializer(),
|
|
223
|
-
help_text="List of method statistics"
|
|
224
|
-
)
|
|
225
|
-
count = serializers.IntegerField(
|
|
226
|
-
help_text="Total number of methods"
|
|
227
|
-
)
|
|
228
|
-
total_calls = serializers.IntegerField(
|
|
229
|
-
help_text="Total calls across all methods"
|
|
230
|
-
)
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
# Testing Serializers
|
|
234
|
-
|
|
235
|
-
class TestRPCRequestSerializer(serializers.Serializer):
|
|
236
|
-
"""Serializer for test RPC request input."""
|
|
237
|
-
|
|
238
|
-
method = serializers.CharField(
|
|
239
|
-
help_text="RPC method to call"
|
|
240
|
-
)
|
|
241
|
-
params = serializers.JSONField(
|
|
242
|
-
help_text="Parameters for the RPC call"
|
|
243
|
-
)
|
|
244
|
-
timeout = serializers.IntegerField(
|
|
245
|
-
default=10,
|
|
246
|
-
min_value=1,
|
|
247
|
-
max_value=60,
|
|
248
|
-
help_text="Timeout in seconds"
|
|
249
|
-
)
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
class TestRPCResponseSerializer(serializers.Serializer):
|
|
253
|
-
"""Serializer for test RPC response."""
|
|
254
|
-
|
|
255
|
-
success = serializers.BooleanField(
|
|
256
|
-
help_text="Whether the call was successful"
|
|
257
|
-
)
|
|
258
|
-
duration_ms = serializers.FloatField(
|
|
259
|
-
help_text="Call duration in milliseconds"
|
|
260
|
-
)
|
|
261
|
-
response = serializers.JSONField(
|
|
262
|
-
allow_null=True,
|
|
263
|
-
required=False,
|
|
264
|
-
help_text="Response data from RPC call"
|
|
265
|
-
)
|
|
266
|
-
error = serializers.CharField(
|
|
267
|
-
allow_null=True,
|
|
268
|
-
required=False,
|
|
269
|
-
help_text="Error message if failed"
|
|
270
|
-
)
|
|
271
|
-
correlation_id = serializers.CharField(
|
|
272
|
-
help_text="Correlation ID for tracking"
|
|
273
|
-
)
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
class LoadTestRequestSerializer(serializers.Serializer):
|
|
277
|
-
"""Serializer for load test request input."""
|
|
278
|
-
|
|
279
|
-
method = serializers.CharField(
|
|
280
|
-
help_text="RPC method to test"
|
|
281
|
-
)
|
|
282
|
-
total_requests = serializers.IntegerField(
|
|
283
|
-
min_value=1,
|
|
284
|
-
max_value=10000,
|
|
285
|
-
help_text="Total number of requests to send"
|
|
286
|
-
)
|
|
287
|
-
concurrency = serializers.IntegerField(
|
|
288
|
-
min_value=1,
|
|
289
|
-
max_value=100,
|
|
290
|
-
help_text="Number of concurrent requests"
|
|
291
|
-
)
|
|
292
|
-
params = serializers.JSONField(
|
|
293
|
-
required=False,
|
|
294
|
-
default=dict,
|
|
295
|
-
help_text="Parameters template for RPC calls"
|
|
296
|
-
)
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
class LoadTestResponseSerializer(serializers.Serializer):
|
|
300
|
-
"""Serializer for load test response."""
|
|
301
|
-
|
|
302
|
-
test_id = serializers.CharField(
|
|
303
|
-
help_text="Unique test ID"
|
|
304
|
-
)
|
|
305
|
-
started = serializers.BooleanField(
|
|
306
|
-
help_text="Whether test was started successfully"
|
|
307
|
-
)
|
|
308
|
-
message = serializers.CharField(
|
|
309
|
-
help_text="Status message"
|
|
310
|
-
)
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
class LoadTestStatusSerializer(serializers.Serializer):
|
|
314
|
-
"""Serializer for load test status."""
|
|
315
|
-
|
|
316
|
-
test_id = serializers.CharField(
|
|
317
|
-
allow_null=True,
|
|
318
|
-
help_text="Unique test ID"
|
|
319
|
-
)
|
|
320
|
-
running = serializers.BooleanField(
|
|
321
|
-
help_text="Whether test is currently running"
|
|
322
|
-
)
|
|
323
|
-
progress = serializers.IntegerField(
|
|
324
|
-
help_text="Number of completed requests"
|
|
325
|
-
)
|
|
326
|
-
total = serializers.IntegerField(
|
|
327
|
-
help_text="Total number of requests"
|
|
328
|
-
)
|
|
329
|
-
success_count = serializers.IntegerField(
|
|
330
|
-
help_text="Number of successful requests"
|
|
331
|
-
)
|
|
332
|
-
failed_count = serializers.IntegerField(
|
|
333
|
-
help_text="Number of failed requests"
|
|
334
|
-
)
|
|
335
|
-
avg_duration_ms = serializers.FloatField(
|
|
336
|
-
help_text="Average duration in milliseconds"
|
|
337
|
-
)
|
|
338
|
-
elapsed_time = serializers.FloatField(
|
|
339
|
-
help_text="Total elapsed time in seconds"
|
|
340
|
-
)
|
|
341
|
-
rps = serializers.FloatField(
|
|
342
|
-
help_text="Requests per second"
|
|
343
|
-
)
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
RPC Client services for IPC module.
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
from .client import DjangoCfgRPCClient
|
|
6
|
-
from .config import DjangoCfgRPCConfig
|
|
7
|
-
from .exceptions import (
|
|
8
|
-
RPCBaseException,
|
|
9
|
-
RPCConfigurationError,
|
|
10
|
-
RPCConnectionError,
|
|
11
|
-
RPCRemoteError,
|
|
12
|
-
RPCTimeoutError,
|
|
13
|
-
)
|
|
14
|
-
|
|
15
|
-
__all__ = [
|
|
16
|
-
'DjangoCfgRPCClient',
|
|
17
|
-
'DjangoCfgRPCConfig',
|
|
18
|
-
'RPCBaseException',
|
|
19
|
-
'RPCConfigurationError',
|
|
20
|
-
'RPCConnectionError',
|
|
21
|
-
'RPCRemoteError',
|
|
22
|
-
'RPCTimeoutError',
|
|
23
|
-
]
|