django-cfg 1.4.62__py3-none-any.whl → 1.4.63__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.

Files changed (181) hide show
  1. django_cfg/__init__.py +1 -1
  2. django_cfg/apps/accounts/services/otp_service.py +3 -14
  3. django_cfg/apps/centrifugo/__init__.py +57 -0
  4. django_cfg/apps/centrifugo/admin/__init__.py +13 -0
  5. django_cfg/apps/centrifugo/admin/centrifugo_log.py +249 -0
  6. django_cfg/apps/centrifugo/admin/config.py +82 -0
  7. django_cfg/apps/centrifugo/apps.py +31 -0
  8. django_cfg/apps/centrifugo/codegen/IMPLEMENTATION_SUMMARY.md +475 -0
  9. django_cfg/apps/centrifugo/codegen/README.md +242 -0
  10. django_cfg/apps/centrifugo/codegen/USAGE.md +616 -0
  11. django_cfg/apps/centrifugo/codegen/__init__.py +19 -0
  12. django_cfg/apps/centrifugo/codegen/discovery.py +246 -0
  13. django_cfg/apps/centrifugo/codegen/generators/go_thin/__init__.py +5 -0
  14. django_cfg/apps/centrifugo/codegen/generators/go_thin/generator.py +174 -0
  15. django_cfg/apps/centrifugo/codegen/generators/go_thin/templates/README.md.j2 +182 -0
  16. django_cfg/apps/centrifugo/codegen/generators/go_thin/templates/client.go.j2 +64 -0
  17. django_cfg/apps/centrifugo/codegen/generators/go_thin/templates/go.mod.j2 +10 -0
  18. django_cfg/apps/centrifugo/codegen/generators/go_thin/templates/rpc_client.go.j2 +300 -0
  19. django_cfg/apps/centrifugo/codegen/generators/go_thin/templates/rpc_client.go.j2.old +267 -0
  20. django_cfg/apps/centrifugo/codegen/generators/go_thin/templates/types.go.j2 +16 -0
  21. django_cfg/apps/centrifugo/codegen/generators/python_thin/__init__.py +7 -0
  22. django_cfg/apps/centrifugo/codegen/generators/python_thin/generator.py +241 -0
  23. django_cfg/apps/centrifugo/codegen/generators/python_thin/templates/README.md.j2 +128 -0
  24. django_cfg/apps/centrifugo/codegen/generators/python_thin/templates/__init__.py.j2 +22 -0
  25. django_cfg/apps/centrifugo/codegen/generators/python_thin/templates/client.py.j2 +73 -0
  26. django_cfg/apps/centrifugo/codegen/generators/python_thin/templates/models.py.j2 +19 -0
  27. django_cfg/apps/centrifugo/codegen/generators/python_thin/templates/requirements.txt.j2 +8 -0
  28. django_cfg/apps/centrifugo/codegen/generators/python_thin/templates/rpc_client.py.j2 +193 -0
  29. django_cfg/apps/centrifugo/codegen/generators/typescript_thin/__init__.py +5 -0
  30. django_cfg/apps/centrifugo/codegen/generators/typescript_thin/generator.py +124 -0
  31. django_cfg/apps/centrifugo/codegen/generators/typescript_thin/templates/README.md.j2 +38 -0
  32. django_cfg/apps/centrifugo/codegen/generators/typescript_thin/templates/client.ts.j2 +25 -0
  33. django_cfg/apps/centrifugo/codegen/generators/typescript_thin/templates/index.ts.j2 +12 -0
  34. django_cfg/apps/centrifugo/codegen/generators/typescript_thin/templates/package.json.j2 +13 -0
  35. django_cfg/apps/centrifugo/codegen/generators/typescript_thin/templates/rpc-client.ts.j2 +137 -0
  36. django_cfg/apps/centrifugo/codegen/generators/typescript_thin/templates/tsconfig.json.j2 +14 -0
  37. django_cfg/apps/centrifugo/codegen/generators/typescript_thin/templates/types.ts.j2 +9 -0
  38. django_cfg/apps/centrifugo/codegen/utils/__init__.py +37 -0
  39. django_cfg/apps/centrifugo/codegen/utils/naming.py +155 -0
  40. django_cfg/apps/centrifugo/codegen/utils/type_converter.py +349 -0
  41. django_cfg/apps/centrifugo/decorators.py +137 -0
  42. django_cfg/apps/centrifugo/management/__init__.py +1 -0
  43. django_cfg/apps/centrifugo/management/commands/__init__.py +1 -0
  44. django_cfg/apps/centrifugo/management/commands/generate_centrifugo_clients.py +254 -0
  45. django_cfg/apps/centrifugo/managers/__init__.py +12 -0
  46. django_cfg/apps/centrifugo/managers/centrifugo_log.py +264 -0
  47. django_cfg/apps/centrifugo/migrations/0001_initial.py +164 -0
  48. django_cfg/apps/centrifugo/migrations/__init__.py +3 -0
  49. django_cfg/apps/centrifugo/models/__init__.py +11 -0
  50. django_cfg/apps/centrifugo/models/centrifugo_log.py +210 -0
  51. django_cfg/apps/centrifugo/registry.py +106 -0
  52. django_cfg/apps/centrifugo/router.py +125 -0
  53. django_cfg/apps/centrifugo/serializers/__init__.py +40 -0
  54. django_cfg/apps/centrifugo/serializers/admin_api.py +264 -0
  55. django_cfg/apps/centrifugo/serializers/channels.py +26 -0
  56. django_cfg/apps/centrifugo/serializers/health.py +17 -0
  57. django_cfg/apps/centrifugo/serializers/publishes.py +16 -0
  58. django_cfg/apps/centrifugo/serializers/stats.py +21 -0
  59. django_cfg/apps/centrifugo/services/__init__.py +12 -0
  60. django_cfg/apps/centrifugo/services/client/__init__.py +29 -0
  61. django_cfg/apps/centrifugo/services/client/client.py +577 -0
  62. django_cfg/apps/centrifugo/services/client/config.py +228 -0
  63. django_cfg/apps/centrifugo/services/client/exceptions.py +212 -0
  64. django_cfg/apps/centrifugo/services/config_helper.py +63 -0
  65. django_cfg/apps/centrifugo/services/dashboard_notifier.py +157 -0
  66. django_cfg/apps/centrifugo/services/logging.py +677 -0
  67. django_cfg/apps/centrifugo/static/django_cfg_centrifugo/css/dashboard.css +260 -0
  68. django_cfg/apps/centrifugo/static/django_cfg_centrifugo/js/dashboard/live_channels.mjs +313 -0
  69. django_cfg/apps/centrifugo/static/django_cfg_centrifugo/js/dashboard/live_testing.mjs +803 -0
  70. django_cfg/apps/centrifugo/static/django_cfg_centrifugo/js/dashboard/main.mjs +333 -0
  71. django_cfg/apps/centrifugo/static/django_cfg_centrifugo/js/dashboard/overview.mjs +432 -0
  72. django_cfg/apps/centrifugo/static/django_cfg_centrifugo/js/dashboard/testing.mjs +33 -0
  73. django_cfg/apps/centrifugo/static/django_cfg_centrifugo/js/dashboard/websocket.mjs +210 -0
  74. django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/components/channels_content.html +46 -0
  75. django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/components/live_channels_content.html +123 -0
  76. django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/components/overview_content.html +45 -0
  77. django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/components/publishes_content.html +84 -0
  78. django_cfg/apps/{ipc/templates/django_cfg_ipc → centrifugo/templates/django_cfg_centrifugo}/components/stat_cards.html +23 -20
  79. django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/components/system_status.html +91 -0
  80. django_cfg/apps/{ipc/templates/django_cfg_ipc → centrifugo/templates/django_cfg_centrifugo}/components/tab_navigation.html +15 -15
  81. django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/components/testing_tools.html +415 -0
  82. django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/layout/base.html +61 -0
  83. django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/pages/dashboard.html +58 -0
  84. django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/tags/connection_script.html +48 -0
  85. django_cfg/apps/centrifugo/templatetags/__init__.py +1 -0
  86. django_cfg/apps/centrifugo/templatetags/centrifugo_tags.py +81 -0
  87. django_cfg/apps/centrifugo/urls.py +31 -0
  88. django_cfg/apps/{ipc → centrifugo}/urls_admin.py +4 -4
  89. django_cfg/apps/centrifugo/views/__init__.py +15 -0
  90. django_cfg/apps/centrifugo/views/admin_api.py +374 -0
  91. django_cfg/apps/centrifugo/views/dashboard.py +15 -0
  92. django_cfg/apps/centrifugo/views/monitoring.py +286 -0
  93. django_cfg/apps/centrifugo/views/testing_api.py +422 -0
  94. django_cfg/apps/support/utils/support_email_service.py +5 -18
  95. django_cfg/apps/tasks/templates/tasks/layout/base.html +0 -2
  96. django_cfg/apps/urls.py +5 -5
  97. django_cfg/core/base/config_model.py +4 -44
  98. django_cfg/core/builders/apps_builder.py +2 -2
  99. django_cfg/core/generation/integration_generators/third_party.py +8 -8
  100. django_cfg/core/utils/__init__.py +5 -0
  101. django_cfg/core/utils/url_helpers.py +73 -0
  102. django_cfg/modules/base.py +7 -7
  103. django_cfg/modules/django_client/core/__init__.py +2 -1
  104. django_cfg/modules/django_client/core/config/config.py +8 -0
  105. django_cfg/modules/django_client/core/generator/__init__.py +42 -2
  106. django_cfg/modules/django_client/core/generator/go/__init__.py +14 -0
  107. django_cfg/modules/django_client/core/generator/go/client_generator.py +124 -0
  108. django_cfg/modules/django_client/core/generator/go/files_generator.py +133 -0
  109. django_cfg/modules/django_client/core/generator/go/generator.py +203 -0
  110. django_cfg/modules/django_client/core/generator/go/models_generator.py +304 -0
  111. django_cfg/modules/django_client/core/generator/go/naming.py +193 -0
  112. django_cfg/modules/django_client/core/generator/go/operations_generator.py +134 -0
  113. django_cfg/modules/django_client/core/generator/go/templates/Makefile.j2 +38 -0
  114. django_cfg/modules/django_client/core/generator/go/templates/README.md.j2 +55 -0
  115. django_cfg/modules/django_client/core/generator/go/templates/client.go.j2 +122 -0
  116. django_cfg/modules/django_client/core/generator/go/templates/enums.go.j2 +49 -0
  117. django_cfg/modules/django_client/core/generator/go/templates/errors.go.j2 +182 -0
  118. django_cfg/modules/django_client/core/generator/go/templates/go.mod.j2 +6 -0
  119. django_cfg/modules/django_client/core/generator/go/templates/main_client.go.j2 +60 -0
  120. django_cfg/modules/django_client/core/generator/go/templates/middleware.go.j2 +388 -0
  121. django_cfg/modules/django_client/core/generator/go/templates/models.go.j2 +28 -0
  122. django_cfg/modules/django_client/core/generator/go/templates/operations_client.go.j2 +142 -0
  123. django_cfg/modules/django_client/core/generator/go/templates/validation.go.j2 +217 -0
  124. django_cfg/modules/django_client/core/generator/go/type_mapper.py +380 -0
  125. django_cfg/modules/django_client/management/commands/generate_client.py +53 -3
  126. django_cfg/modules/django_client/system/generate_mjs_clients.py +3 -1
  127. django_cfg/modules/django_client/system/schema_parser.py +5 -1
  128. django_cfg/modules/django_tailwind/templates/django_tailwind/base.html +1 -0
  129. django_cfg/modules/django_twilio/sendgrid_service.py +7 -4
  130. django_cfg/modules/django_unfold/dashboard.py +25 -19
  131. django_cfg/pyproject.toml +1 -1
  132. django_cfg/registry/core.py +2 -0
  133. django_cfg/registry/modules.py +2 -2
  134. django_cfg/static/js/api/centrifugo/client.mjs +164 -0
  135. django_cfg/static/js/api/centrifugo/index.mjs +13 -0
  136. django_cfg/static/js/api/index.mjs +5 -5
  137. django_cfg/static/js/api/types.mjs +89 -26
  138. {django_cfg-1.4.62.dist-info → django_cfg-1.4.63.dist-info}/METADATA +1 -1
  139. {django_cfg-1.4.62.dist-info → django_cfg-1.4.63.dist-info}/RECORD +142 -70
  140. django_cfg/apps/ipc/README.md +0 -346
  141. django_cfg/apps/ipc/RPC_LOGGING.md +0 -321
  142. django_cfg/apps/ipc/TESTING.md +0 -539
  143. django_cfg/apps/ipc/__init__.py +0 -60
  144. django_cfg/apps/ipc/admin.py +0 -232
  145. django_cfg/apps/ipc/apps.py +0 -98
  146. django_cfg/apps/ipc/migrations/0001_initial.py +0 -137
  147. django_cfg/apps/ipc/migrations/0002_rpclog_is_event.py +0 -23
  148. django_cfg/apps/ipc/migrations/__init__.py +0 -0
  149. django_cfg/apps/ipc/models.py +0 -229
  150. django_cfg/apps/ipc/serializers/__init__.py +0 -29
  151. django_cfg/apps/ipc/serializers/serializers.py +0 -343
  152. django_cfg/apps/ipc/services/__init__.py +0 -7
  153. django_cfg/apps/ipc/services/client/__init__.py +0 -23
  154. django_cfg/apps/ipc/services/client/client.py +0 -621
  155. django_cfg/apps/ipc/services/client/config.py +0 -214
  156. django_cfg/apps/ipc/services/client/exceptions.py +0 -201
  157. django_cfg/apps/ipc/services/logging.py +0 -239
  158. django_cfg/apps/ipc/services/monitor.py +0 -466
  159. django_cfg/apps/ipc/services/rpc_log_consumer.py +0 -330
  160. django_cfg/apps/ipc/static/django_cfg_ipc/js/dashboard/main.mjs +0 -269
  161. django_cfg/apps/ipc/static/django_cfg_ipc/js/dashboard/overview.mjs +0 -259
  162. django_cfg/apps/ipc/static/django_cfg_ipc/js/dashboard/testing.mjs +0 -375
  163. django_cfg/apps/ipc/static/django_cfg_ipc/js/dashboard.mjs.old +0 -441
  164. django_cfg/apps/ipc/templates/django_cfg_ipc/components/methods_content.html +0 -22
  165. django_cfg/apps/ipc/templates/django_cfg_ipc/components/notifications_content.html +0 -9
  166. django_cfg/apps/ipc/templates/django_cfg_ipc/components/overview_content.html +0 -9
  167. django_cfg/apps/ipc/templates/django_cfg_ipc/components/requests_content.html +0 -23
  168. django_cfg/apps/ipc/templates/django_cfg_ipc/components/system_status.html +0 -47
  169. django_cfg/apps/ipc/templates/django_cfg_ipc/components/testing_tools.html +0 -184
  170. django_cfg/apps/ipc/templates/django_cfg_ipc/layout/base.html +0 -71
  171. django_cfg/apps/ipc/templates/django_cfg_ipc/pages/dashboard.html +0 -56
  172. django_cfg/apps/ipc/urls.py +0 -23
  173. django_cfg/apps/ipc/views/__init__.py +0 -13
  174. django_cfg/apps/ipc/views/dashboard.py +0 -15
  175. django_cfg/apps/ipc/views/monitoring.py +0 -251
  176. django_cfg/apps/ipc/views/testing.py +0 -285
  177. django_cfg/static/js/api/ipc/client.mjs +0 -114
  178. django_cfg/static/js/api/ipc/index.mjs +0 -13
  179. {django_cfg-1.4.62.dist-info → django_cfg-1.4.63.dist-info}/WHEEL +0 -0
  180. {django_cfg-1.4.62.dist-info → django_cfg-1.4.63.dist-info}/entry_points.txt +0 -0
  181. {django_cfg-1.4.62.dist-info → django_cfg-1.4.63.dist-info}/licenses/LICENSE +0 -0
@@ -1,232 +0,0 @@
1
- """
2
- Django Admin for IPC/RPC models.
3
-
4
- Uses PydanticAdmin with declarative configuration.
5
- """
6
-
7
- import json
8
-
9
- from django.contrib import admin
10
- from django_cfg.modules.django_admin import (
11
- AdminConfig,
12
- BadgeField,
13
- DateTimeField,
14
- Icons,
15
- UserField,
16
- computed_field,
17
- )
18
- from django_cfg.modules.django_admin.base import PydanticAdmin
19
-
20
- from .models import RPCLog
21
-
22
-
23
- # Declarative configuration for RPCLog
24
- rpclog_config = AdminConfig(
25
- model=RPCLog,
26
-
27
- # Performance optimization
28
- select_related=["user"],
29
-
30
- # List display
31
- list_display=[
32
- "method",
33
- "type_badge", # NEW: Show RPC vs Event
34
- "status",
35
- "user",
36
- "duration_ms",
37
- "created_at",
38
- "completed_at"
39
- ],
40
-
41
- # Auto-generated display methods
42
- display_fields=[
43
- BadgeField(
44
- name="method",
45
- title="RPC Method",
46
- variant="info",
47
- icon=Icons.API
48
- ),
49
- BadgeField(
50
- name="status",
51
- title="Status",
52
- label_map={
53
- "pending": "warning",
54
- "success": "success",
55
- "failed": "danger",
56
- "timeout": "danger"
57
- }
58
- ),
59
- UserField(
60
- name="user",
61
- title="User",
62
- header=True # Show with avatar
63
- ),
64
- DateTimeField(
65
- name="created_at",
66
- title="Created",
67
- ordering="created_at"
68
- ),
69
- DateTimeField(
70
- name="completed_at",
71
- title="Completed",
72
- ordering="completed_at"
73
- ),
74
- ],
75
-
76
- # Filters
77
- list_filter=["status", "is_event", "method", "created_at"],
78
- search_fields=["method", "correlation_id", "user__username", "user__email", "error_message"],
79
-
80
- # Autocomplete for user field
81
- autocomplete_fields=["user"],
82
-
83
- # Readonly fields (custom methods below)
84
- readonly_fields=[
85
- "id",
86
- "correlation_id",
87
- "created_at",
88
- "completed_at",
89
- "params_display",
90
- "response_display",
91
- "error_details_display"
92
- ],
93
-
94
- # Date hierarchy
95
- date_hierarchy="created_at",
96
-
97
- # Per page
98
- list_per_page=50,
99
- )
100
-
101
-
102
- @admin.register(RPCLog)
103
- class RPCLogAdmin(PydanticAdmin):
104
- """
105
- RPC log admin with analytics and filtering.
106
-
107
- Features:
108
- - Color-coded status badges
109
- - Duration display with performance indicators
110
- - Formatted JSON for params/response
111
- - Error details with highlighted display
112
- """
113
- config = rpclog_config
114
-
115
- @computed_field("Type", ordering="is_event")
116
- def type_badge(self, obj):
117
- """Display badge showing if this is an RPC call or server event."""
118
- if obj.is_event:
119
- return self.html.badge(
120
- "EVENT",
121
- variant="info",
122
- icon=Icons.NOTIFICATION # or Icons.BROADCAST
123
- )
124
- else:
125
- return self.html.badge(
126
- "RPC",
127
- variant="primary",
128
- icon=Icons.API
129
- )
130
-
131
- @computed_field("Duration", ordering="duration_ms")
132
- def duration_display(self, obj):
133
- """Display duration with color coding based on speed."""
134
- if obj.duration_ms is None:
135
- return self.html.empty()
136
-
137
- # Color code based on duration
138
- if obj.duration_ms < 100:
139
- variant = "success" # Fast
140
- icon = Icons.SPEED
141
- elif obj.duration_ms < 500:
142
- variant = "warning" # Moderate
143
- icon = Icons.TIMER
144
- else:
145
- variant = "danger" # Slow
146
- icon = Icons.ERROR
147
-
148
- return self.html.badge(
149
- f"{obj.duration_ms}ms",
150
- variant=variant,
151
- icon=icon
152
- )
153
-
154
- def params_display(self, obj):
155
- """Display formatted JSON params."""
156
- if not obj.params:
157
- return self.html.empty("No parameters")
158
-
159
- try:
160
- formatted = json.dumps(obj.params, indent=2)
161
- return f'<pre style="background: #f5f5f5; padding: 10px; border-radius: 4px; max-height: 400px; overflow: auto; font-size: 12px; line-height: 1.5;">{formatted}</pre>'
162
- except Exception:
163
- return str(obj.params)
164
-
165
- params_display.short_description = "Request Parameters"
166
-
167
- def response_display(self, obj):
168
- """Display formatted JSON response."""
169
- if not obj.response:
170
- return self.html.empty("No response")
171
-
172
- try:
173
- formatted = json.dumps(obj.response, indent=2)
174
- return f'<pre style="background: #f5f5f5; padding: 10px; border-radius: 4px; max-height: 400px; overflow: auto; font-size: 12px; line-height: 1.5;">{formatted}</pre>'
175
- except Exception:
176
- return str(obj.response)
177
-
178
- response_display.short_description = "Response Data"
179
-
180
- def error_details_display(self, obj):
181
- """Display error information if call failed."""
182
- if not obj.is_failed:
183
- return self.html.inline([
184
- self.html.icon(Icons.CHECK_CIRCLE, size="sm"),
185
- self.html.span("No errors", "text-green-600")
186
- ])
187
-
188
- details = []
189
-
190
- if obj.error_code:
191
- details.append(self.html.inline([
192
- self.html.span("Error Code:", "font-semibold"),
193
- self.html.badge(obj.error_code, variant="danger", icon=Icons.ERROR)
194
- ], separator=" "))
195
-
196
- if obj.error_message:
197
- details.append(self.html.inline([
198
- self.html.span("Message:", "font-semibold"),
199
- self.html.span(obj.error_message, "text-red-600")
200
- ], separator=" "))
201
-
202
- return "<br>".join(details) if details else self.html.empty()
203
-
204
- error_details_display.short_description = "Error Details"
205
-
206
- # Fieldsets for detail view
207
- def get_fieldsets(self, request, obj=None):
208
- """Dynamic fieldsets based on object state."""
209
- fieldsets = [
210
- ("RPC Call Information", {
211
- 'fields': ('id', 'correlation_id', 'method', 'user', 'status')
212
- }),
213
- ("Request & Response", {
214
- 'fields': ('params_display', 'response_display'),
215
- 'classes': ('collapse',)
216
- }),
217
- ("Performance", {
218
- 'fields': ('duration_ms', 'created_at', 'completed_at')
219
- }),
220
- ("Metadata", {
221
- 'fields': ('caller_ip', 'user_agent'),
222
- 'classes': ('collapse',)
223
- }),
224
- ]
225
-
226
- # Add error section only if failed
227
- if obj and obj.is_failed:
228
- fieldsets.insert(2, ("Error Details", {
229
- 'fields': ('error_details_display', 'error_code', 'error_message')
230
- }))
231
-
232
- return fieldsets
@@ -1,98 +0,0 @@
1
- """
2
- Django app configuration for IPC/RPC module.
3
-
4
- Provides RPC client and monitoring dashboard.
5
- """
6
-
7
- import asyncio
8
- from django.apps import AppConfig
9
- from django.conf import settings
10
-
11
-
12
- class IPCConfig(AppConfig):
13
- """
14
- IPC/RPC application configuration.
15
-
16
- Provides:
17
- - RPC client for inter-service communication
18
- - Monitoring dashboard with real-time stats
19
- - DRF API endpoints for dashboard
20
- - RPC log consumer (Redis Stream -> ORM)
21
- """
22
-
23
- default_auto_field = 'django.db.models.BigAutoField'
24
- name = 'django_cfg.apps.ipc'
25
- label = 'django_cfg_ipc'
26
- verbose_name = 'IPC/RPC System'
27
-
28
- def ready(self):
29
- """Initialize app when Django starts."""
30
- # Import monitor to ensure Redis connection is initialized
31
- from .services import monitor # noqa: F401
32
-
33
- # Start RPC Log Consumer in background (if enabled)
34
- self._start_rpc_log_consumer()
35
-
36
- def _start_rpc_log_consumer(self):
37
- """Start RPC Log Consumer to capture logs from WebSocket server."""
38
- # Check if RPC logging consumer is enabled
39
- enable_consumer = getattr(settings, 'DJANGO_CFG_RPC_LOG_CONSUMER_ENABLED', True)
40
-
41
- if not enable_consumer:
42
- return
43
-
44
- # Check if we have RPC configuration
45
- if not hasattr(settings, 'DJANGO_CFG_RPC'):
46
- return
47
-
48
- # Check if RPC is enabled (case-insensitive)
49
- rpc_enabled = settings.DJANGO_CFG_RPC.get('ENABLED') or settings.DJANGO_CFG_RPC.get('enabled')
50
- if not rpc_enabled:
51
- return
52
-
53
- try:
54
- import threading
55
- from .services.rpc_log_consumer import RPCLogConsumer
56
-
57
- # Get Redis URL (case-insensitive)
58
- redis_url = settings.DJANGO_CFG_RPC.get('REDIS_URL') or settings.DJANGO_CFG_RPC.get('redis_url', 'redis://localhost:6379/2')
59
-
60
- consumer = RPCLogConsumer(
61
- redis_url=redis_url,
62
- stream_name="stream:rpc-logs",
63
- consumer_group="django-rpc-loggers",
64
- consumer_name="django-1",
65
- )
66
-
67
- # Run consumer in background thread with its own event loop
68
- def run_consumer():
69
- """Run consumer in background thread."""
70
- try:
71
- # Create new event loop for this thread
72
- loop = asyncio.new_event_loop()
73
- asyncio.set_event_loop(loop)
74
-
75
- # Initialize and start consumer
76
- loop.run_until_complete(consumer.initialize())
77
- loop.run_until_complete(consumer.start())
78
-
79
- # Keep running
80
- loop.run_forever()
81
-
82
- except Exception as e:
83
- from django_cfg.modules.django_logging import get_logger
84
- logger = get_logger("ipc.consumer")
85
- logger.error(f"RPC Log Consumer error: {e}", exc_info=True)
86
-
87
- # Start in daemon thread (won't block Django shutdown)
88
- thread = threading.Thread(target=run_consumer, daemon=True, name="rpc-log-consumer")
89
- thread.start()
90
-
91
- from django_cfg.modules.django_logging import get_logger
92
- logger = get_logger("ipc.apps")
93
- logger.info("✅ RPC Log Consumer started in background thread")
94
-
95
- except Exception as e:
96
- from django_cfg.modules.django_logging import get_logger
97
- logger = get_logger("ipc.apps")
98
- logger.warning(f"Failed to start RPC Log Consumer: {e}")
@@ -1,137 +0,0 @@
1
- # Generated by Django 5.2.7 on 2025-10-23 12:12
2
-
3
- import django.db.models.deletion
4
- import django.utils.timezone
5
- import uuid
6
- from django.conf import settings
7
- from django.db import migrations, models
8
-
9
-
10
- class Migration(migrations.Migration):
11
- initial = True
12
-
13
- dependencies = [
14
- migrations.swappable_dependency(settings.AUTH_USER_MODEL),
15
- ]
16
-
17
- operations = [
18
- migrations.CreateModel(
19
- name="RPCLog",
20
- fields=[
21
- (
22
- "id",
23
- models.UUIDField(
24
- default=uuid.uuid4, editable=False, primary_key=True, serialize=False
25
- ),
26
- ),
27
- (
28
- "correlation_id",
29
- models.CharField(
30
- db_index=True,
31
- help_text="UUID from RPC request",
32
- max_length=100,
33
- verbose_name="Correlation ID",
34
- ),
35
- ),
36
- (
37
- "method",
38
- models.CharField(
39
- db_index=True,
40
- help_text="e.g., send_notification, workspace.file_changed",
41
- max_length=100,
42
- verbose_name="RPC Method",
43
- ),
44
- ),
45
- (
46
- "params",
47
- models.JSONField(
48
- help_text="Parameters sent to RPC method", verbose_name="Request Params"
49
- ),
50
- ),
51
- (
52
- "response",
53
- models.JSONField(
54
- blank=True,
55
- help_text="Result from RPC call",
56
- null=True,
57
- verbose_name="Response Data",
58
- ),
59
- ),
60
- (
61
- "status",
62
- models.CharField(
63
- choices=[
64
- ("pending", "Pending"),
65
- ("success", "Success"),
66
- ("failed", "Failed"),
67
- ("timeout", "Timeout"),
68
- ],
69
- db_index=True,
70
- default="pending",
71
- max_length=20,
72
- verbose_name="Status",
73
- ),
74
- ),
75
- (
76
- "error_code",
77
- models.CharField(
78
- blank=True, max_length=50, null=True, verbose_name="Error Code"
79
- ),
80
- ),
81
- (
82
- "error_message",
83
- models.TextField(blank=True, null=True, verbose_name="Error Message"),
84
- ),
85
- (
86
- "duration_ms",
87
- models.IntegerField(
88
- blank=True,
89
- help_text="Time taken for RPC call in milliseconds",
90
- null=True,
91
- verbose_name="Duration (ms)",
92
- ),
93
- ),
94
- (
95
- "caller_ip",
96
- models.GenericIPAddressField(blank=True, null=True, verbose_name="Caller IP"),
97
- ),
98
- ("user_agent", models.TextField(blank=True, null=True, verbose_name="User Agent")),
99
- (
100
- "created_at",
101
- models.DateTimeField(
102
- db_index=True, default=django.utils.timezone.now, verbose_name="Created At"
103
- ),
104
- ),
105
- (
106
- "completed_at",
107
- models.DateTimeField(blank=True, null=True, verbose_name="Completed At"),
108
- ),
109
- (
110
- "user",
111
- models.ForeignKey(
112
- blank=True,
113
- null=True,
114
- on_delete=django.db.models.deletion.SET_NULL,
115
- related_name="rpc_logs",
116
- to=settings.AUTH_USER_MODEL,
117
- verbose_name="User",
118
- ),
119
- ),
120
- ],
121
- options={
122
- "verbose_name": "RPC Log",
123
- "verbose_name_plural": "RPC Logs",
124
- "ordering": ["-created_at"],
125
- "indexes": [
126
- models.Index(fields=["method", "status"], name="django_cfg__method_916fd9_idx"),
127
- models.Index(
128
- fields=["status", "created_at"], name="django_cfg__status_ee629e_idx"
129
- ),
130
- models.Index(fields=["correlation_id"], name="django_cfg__correla_fc7bcf_idx"),
131
- models.Index(
132
- fields=["user", "created_at"], name="django_cfg__user_id_c33866_idx"
133
- ),
134
- ],
135
- },
136
- ),
137
- ]
@@ -1,23 +0,0 @@
1
- # Generated by Django 5.2.7 on 2025-10-24 07:41
2
-
3
- from django.db import migrations, models
4
-
5
-
6
- class Migration(migrations.Migration):
7
-
8
- dependencies = [
9
- ("django_cfg_ipc", "0001_initial"),
10
- ]
11
-
12
- operations = [
13
- migrations.AddField(
14
- model_name="rpclog",
15
- name="is_event",
16
- field=models.BooleanField(
17
- db_index=True,
18
- default=False,
19
- help_text="True if this is a server-to-client event (not a request-response RPC call)",
20
- verbose_name="Is Event",
21
- ),
22
- ),
23
- ]
File without changes