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.

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 +582 -0
  62. django_cfg/apps/centrifugo/services/client/config.py +236 -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 +380 -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.64.dist-info}/METADATA +1 -1
  139. {django_cfg-1.4.62.dist-info → django_cfg-1.4.64.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.64.dist-info}/WHEEL +0 -0
  180. {django_cfg-1.4.62.dist-info → django_cfg-1.4.64.dist-info}/entry_points.txt +0 -0
  181. {django_cfg-1.4.62.dist-info → django_cfg-1.4.64.dist-info}/licenses/LICENSE +0 -0
@@ -1,184 +0,0 @@
1
- <!-- Testing Tools Tab -->
2
- <div id="testing-tab" class="tab-panel hidden">
3
- <!-- RPC Test Client -->
4
- <div class="bg-white dark:bg-gray-800 rounded-lg p-6 border border-gray-200 dark:border-gray-700 mb-6">
5
- <h3 class="text-lg font-bold text-gray-900 dark:text-white mb-4 flex items-center">
6
- <span class="material-icons mr-2 text-blue-500">send</span>
7
- RPC Test Client
8
- </h3>
9
- <p class="text-sm text-gray-600 dark:text-gray-400 mb-4">
10
- Send individual RPC requests to test methods and inspect responses
11
- </p>
12
-
13
- <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
14
- <!-- Method Selection -->
15
- <div>
16
- <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
17
- RPC Method
18
- </label>
19
- <select id="test-rpc-method" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-blue-500 focus:border-blue-500">
20
- <option value="">Select a method...</option>
21
- <option value="notification.send">notification.send</option>
22
- <option value="notification.broadcast">notification.broadcast</option>
23
- <option value="workspace.file_changed">workspace.file_changed</option>
24
- <option value="session.message">session.message</option>
25
- </select>
26
- </div>
27
-
28
- <!-- Timeout -->
29
- <div>
30
- <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
31
- Timeout (seconds)
32
- </label>
33
- <input type="number" id="test-rpc-timeout" value="10" min="1" max="60" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-blue-500 focus:border-blue-500">
34
- </div>
35
- </div>
36
-
37
- <!-- Params JSON Editor -->
38
- <div class="mb-4">
39
- <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
40
- Parameters (JSON)
41
- </label>
42
- <textarea id="test-rpc-params" rows="7" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-white font-mono text-sm focus:ring-blue-5 focus:border-blue-500">{
43
- "user_id": "test-123",
44
- "type": "info",
45
- "title": "Test Notification",
46
- "message": "This is a test message",
47
- "timestamp": "2025-10-23T12:00:00.000Z"
48
- }</textarea>
49
- </div>
50
-
51
- <!-- Action Buttons -->
52
- <div class="flex gap-3">
53
- <button id="send-test-rpc-btn" class="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-md font-medium flex items-center gap-2 transition-colors">
54
- <span class="material-icons text-sm">send</span>
55
- Send Request
56
- </button>
57
- <button id="clear-test-rpc-btn" class="px-4 py-2 bg-gray-500 hover:bg-gray-600 text-white rounded-md font-medium flex items-center gap-2 transition-colors">
58
- <span class="material-icons text-sm">clear</span>
59
- Clear
60
- </button>
61
- </div>
62
-
63
- <!-- Response Display -->
64
- <div id="test-rpc-result" class="mt-4 hidden">
65
- </div>
66
- </div>
67
-
68
- <!-- Load Testing Tool -->
69
- <div class="bg-white dark:bg-gray-800 rounded-lg p-6 border border-gray-200 dark:border-gray-700">
70
- <h3 class="text-lg font-bold text-gray-900 dark:text-white mb-4 flex items-center">
71
- <span class="material-icons mr-2 text-orange-500">speed</span>
72
- Load Testing Tool
73
- </h3>
74
- <p class="text-sm text-gray-600 dark:text-gray-400 mb-4">
75
- Emulate production load by sending multiple concurrent RPC requests
76
- </p>
77
-
78
- <div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-4">
79
- <!-- Total Requests -->
80
- <div>
81
- <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
82
- Total Requests
83
- </label>
84
- <input type="number" id="load-test-total" value="100" min="1" max="10000" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-blue-500 focus:border-blue-500">
85
- </div>
86
-
87
- <!-- Concurrency -->
88
- <div>
89
- <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
90
- Concurrent Requests
91
- </label>
92
- <input type="number" id="load-test-concurrency" value="10" min="1" max="100" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-blue-500 focus:border-blue-500">
93
- </div>
94
-
95
- <!-- Method -->
96
- <div>
97
- <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
98
- Test Method
99
- </label>
100
- <select id="load-test-method" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-blue-500 focus:border-blue-500">
101
- <option value="">Select a method...</option>
102
- <option value="notification.send">notification.send</option>
103
- <option value="notification.broadcast">notification.broadcast</option>
104
- <option value="workspace.file_changed">workspace.file_changed</option>
105
- <option value="session.message">session.message</option>
106
- </select>
107
- </div>
108
- </div>
109
-
110
- <!-- Load Test Params JSON Editor -->
111
- <div class="mb-4">
112
- <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
113
- Request Parameters (JSON)
114
- </label>
115
- <textarea id="load-test-params" rows="5" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-white font-mono text-sm focus:ring-blue-500 focus:border-blue-500">{
116
- "user_id": "load-test-user",
117
- "type": "info",
118
- "title": "Load Test Notification",
119
- "message": "This is a load test message",
120
- "timestamp": "2025-10-23T12:00:00.000Z"
121
- }</textarea>
122
- <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
123
- Note: <code>_test_id</code> and <code>_index</code> will be automatically added to each request.
124
- </p>
125
- </div>
126
-
127
- <!-- Action Buttons -->
128
- <div class="flex gap-3 mb-4">
129
- <button id="start-load-test-btn" class="px-4 py-2 bg-orange-600 hover:bg-orange-700 text-white rounded-md font-medium flex items-center gap-2 transition-colors">
130
- <span class="material-icons text-sm">play_arrow</span>
131
- Start Load Test
132
- </button>
133
- <button id="stop-load-test-btn" class="px-4 py-2 bg-red-600 hover:bg-red-700 text-white rounded-md font-medium flex items-center gap-2 transition-colors opacity-50 cursor-not-allowed" disabled>
134
- <span class="material-icons text-sm">stop</span>
135
- Stop Test
136
- </button>
137
- </div>
138
-
139
- <!-- Progress -->
140
- <div class="mb-4">
141
- <div class="mb-2 flex justify-between text-sm">
142
- <span class="text-gray-700 dark:text-gray-300">Progress: <span id="load-test-progress-text">0/0</span></span>
143
- </div>
144
- <div class="w-full bg-gray-200 dark:bg-gray-700 rounded-full h-2.5 mb-4">
145
- <div id="load-test-progress" class="bg-orange-600 h-2.5 rounded-full transition-all" style="width: 0%"></div>
146
- </div>
147
- </div>
148
-
149
- <!-- Statistics Cards -->
150
- <div class="grid grid-cols-2 md:grid-cols-4 gap-4">
151
- <div class="bg-blue-50 dark:bg-blue-900/20 rounded-lg p-4 border border-blue-200 dark:border-blue-800">
152
- <div class="flex items-center justify-between mb-2">
153
- <span class="material-icons text-xl text-blue-600 dark:text-blue-400">check_circle</span>
154
- </div>
155
- <div class="text-2xl font-bold text-gray-900 dark:text-white" id="load-test-success">0</div>
156
- <div class="text-xs text-gray-600 dark:text-gray-400">Success</div>
157
- </div>
158
-
159
- <div class="bg-red-50 dark:bg-red-900/20 rounded-lg p-4 border border-red-200 dark:border-red-800">
160
- <div class="flex items-center justify-between mb-2">
161
- <span class="material-icons text-xl text-red-600 dark:text-red-400">error</span>
162
- </div>
163
- <div class="text-2xl font-bold text-gray-900 dark:text-white" id="load-test-failed">0</div>
164
- <div class="text-xs text-gray-600 dark:text-gray-400">Failed</div>
165
- </div>
166
-
167
- <div class="bg-green-50 dark:bg-green-900/20 rounded-lg p-4 border border-green-200 dark:border-green-800">
168
- <div class="flex items-center justify-between mb-2">
169
- <span class="material-icons text-xl text-green-600 dark:text-green-400">timer</span>
170
- </div>
171
- <div class="text-2xl font-bold text-gray-900 dark:text-white"><span id="load-test-avg-time">0</span>ms</div>
172
- <div class="text-xs text-gray-600 dark:text-gray-400">Avg Time</div>
173
- </div>
174
-
175
- <div class="bg-purple-50 dark:bg-purple-900/20 rounded-lg p-4 border border-purple-200 dark:border-purple-800">
176
- <div class="flex items-center justify-between mb-2">
177
- <span class="material-icons text-xl text-purple-600 dark:text-purple-400">trending_up</span>
178
- </div>
179
- <div class="text-2xl font-bold text-gray-900 dark:text-white" id="load-test-rps">0</div>
180
- <div class="text-xs text-gray-600 dark:text-gray-400">RPS</div>
181
- </div>
182
- </div>
183
- </div>
184
- </div>
@@ -1,71 +0,0 @@
1
- {% extends 'django_tailwind/app.html' %}
2
- {% load static %}
3
-
4
- {% block title %}{% block page_title_text %}RPC Monitor{% endblock %} - Django-CFG{% endblock %}
5
-
6
- {# Navbar configuration #}
7
- {% block header %}
8
- {% with navbar_items=rpc_nav_items %}
9
- {% include 'django_tailwind/components/navbar.html' with title="RPC Monitor" icon='<span class="material-icons text-3xl text-blue-400">insights</span>' nav_items=navbar_items full_width=True %}
10
- {% endwith %}
11
-
12
- {# RPC-specific header info #}
13
- <div class="bg-gray-50 dark:bg-gray-900 border-b border-gray-200 dark:border-gray-800">
14
- <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-3">
15
- <div class="flex items-center justify-between text-sm">
16
- <p class="text-gray-600 dark:text-gray-400">Real-time WebSocket & RPC Activity</p>
17
-
18
- <div class="flex items-center space-x-4">
19
- <!-- Health indicator -->
20
- <div id="health-indicator" class="flex items-center space-x-2">
21
- <span class="pulse-dot w-2 h-2 bg-green-500 rounded-full"></span>
22
- <span class="text-gray-700 dark:text-gray-300">Connected</span>
23
- </div>
24
-
25
- <!-- Auto-refresh toggle -->
26
- <label class="flex items-center space-x-2 cursor-pointer">
27
- <span class="text-gray-700 dark:text-gray-300">Auto-refresh</span>
28
- <input type="checkbox" id="auto-refresh-toggle" checked
29
- class="toggle-checkbox rounded border-gray-400 dark:border-gray-600 text-blue-600 dark:text-blue-400 focus:ring-blue-500 dark:focus:ring-blue-400">
30
- </label>
31
- </div>
32
- </div>
33
- </div>
34
- </div>
35
- {% endblock %}
36
-
37
- {% block extra_head %}
38
- {{ block.super }}
39
- <!-- Material Icons -->
40
- <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
41
-
42
- <style>
43
- .stat-card {
44
- transition: transform 0.2s, box-shadow 0.2s;
45
- }
46
-
47
- .stat-card:hover {
48
- transform: translateY(-2px);
49
- box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);
50
- }
51
-
52
- .pulse-dot {
53
- animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
54
- }
55
-
56
- @keyframes pulse {
57
- 0%, 100% {
58
- opacity: 1;
59
- }
60
- 50% {
61
- opacity: 0.5;
62
- }
63
- }
64
- </style>
65
-
66
- {% block extra_css %}{% endblock %}
67
- {% endblock %}
68
-
69
- {% block body %}
70
- {{ block.super }}
71
- {% endblock %}
@@ -1,56 +0,0 @@
1
- {% extends 'django_cfg_ipc/layout/base.html' %}
2
- {% load static %}
3
-
4
- {% block title %}RPC Monitor Dashboard{% endblock %}
5
-
6
- {% block content %}
7
- <!-- Statistics Cards -->
8
- {% include 'django_cfg_ipc/components/stat_cards.html' %}
9
-
10
- <!-- System Status -->
11
- {% include 'django_cfg_ipc/components/system_status.html' %}
12
-
13
- <!-- Tab Navigation -->
14
- {% include 'django_cfg_ipc/components/tab_navigation.html' %}
15
-
16
- <!-- Tab Content -->
17
- <div class="tab-content">
18
- {% include 'django_cfg_ipc/components/overview_content.html' %}
19
- {% include 'django_cfg_ipc/components/requests_content.html' %}
20
- {% include 'django_cfg_ipc/components/notifications_content.html' %}
21
- {% include 'django_cfg_ipc/components/methods_content.html' %}
22
- {% include 'django_cfg_ipc/components/testing_tools.html' %}
23
- </div>
24
- {% endblock %}
25
-
26
- {% block extra_js %}
27
- {% load i18n %}
28
- {% now "U" as current_timestamp %}
29
-
30
- <!-- Load and initialize IPC API -->
31
- <script type="module">
32
- try {
33
- console.log('🔄 Starting IpcAPI module import...');
34
- const { loadAPI, showNotification } = await import('/static/js/api-loader.mjs');
35
-
36
- // Load ipc API
37
- const ipcAPI = await loadAPI('ipc');
38
- console.log('✅ IpcAPI module imported successfully:', ipcAPI);
39
-
40
- // Make it available globally as ipcAPI
41
- window.ipcAPI = ipcAPI;
42
- window.showNotification = showNotification;
43
-
44
- console.log('✅ IpcAPI loaded from generated MJS client');
45
- } catch (error) {
46
- console.error('❌ Failed to load IpcAPI module:', error);
47
- console.error('Error stack:', error.stack);
48
- window.ipcAPI = null;
49
- }
50
- </script>
51
-
52
- <!-- Dashboard Modules -->
53
- <script type="module" src="{% static 'django_cfg_ipc/js/dashboard/overview.mjs' %}?v={{ current_timestamp }}"></script>
54
- <script type="module" src="{% static 'django_cfg_ipc/js/dashboard/testing.mjs' %}?v={{ current_timestamp }}"></script>
55
- <script type="module" src="{% static 'django_cfg_ipc/js/dashboard/main.mjs' %}?v={{ current_timestamp }}"></script>
56
- {% endblock %}
@@ -1,23 +0,0 @@
1
- """
2
- URL patterns for IPC/RPC module.
3
-
4
- Public API endpoints for RPC monitoring and testing using DRF router.
5
- """
6
-
7
- from django.urls import include, path
8
- from rest_framework import routers
9
-
10
- from .views.monitoring import RPCMonitorViewSet
11
- from .views.testing import RPCTestingViewSet
12
-
13
- app_name = 'django_cfg_ipc'
14
-
15
- # Create router
16
- router = routers.DefaultRouter()
17
- router.register(r'monitor', RPCMonitorViewSet, basename='monitor')
18
- router.register(r'test', RPCTestingViewSet, basename='test')
19
-
20
- urlpatterns = [
21
- # Include router URLs
22
- path('', include(router.urls)),
23
- ]
@@ -1,13 +0,0 @@
1
- """
2
- Views for IPC/RPC module.
3
- """
4
-
5
- from .dashboard import dashboard_view
6
- from .monitoring import RPCMonitorViewSet
7
- from .testing import RPCTestingViewSet
8
-
9
- __all__ = [
10
- 'RPCMonitorViewSet',
11
- 'RPCTestingViewSet',
12
- 'dashboard_view',
13
- ]
@@ -1,15 +0,0 @@
1
- """
2
- Dashboard view for IPC/RPC monitoring.
3
- """
4
-
5
- from django.contrib.admin.views.decorators import staff_member_required
6
- from django.shortcuts import render
7
-
8
-
9
- @staff_member_required
10
- def dashboard_view(request):
11
- """Render the IPC/RPC dashboard template."""
12
- context = {
13
- 'page_title': 'IPC/RPC Monitor Dashboard',
14
- }
15
- return render(request, 'django_cfg_ipc/pages/dashboard.html', context)
@@ -1,251 +0,0 @@
1
- """
2
- RPC Monitoring ViewSet.
3
-
4
- Provides REST API endpoints for monitoring RPC system health and statistics.
5
- """
6
-
7
- from django_cfg.modules.django_logging import get_logger
8
- from drf_spectacular.types import OpenApiTypes
9
- from drf_spectacular.utils import OpenApiParameter, extend_schema
10
- from rest_framework import status, viewsets
11
- from rest_framework.authentication import SessionAuthentication
12
- from rest_framework.decorators import action
13
- from rest_framework.permissions import IsAdminUser
14
- from rest_framework.response import Response
15
-
16
- from ..serializers import (
17
- HealthCheckSerializer,
18
- MethodStatsSerializer,
19
- NotificationStatsSerializer,
20
- OverviewStatsSerializer,
21
- RecentRequestsSerializer,
22
- )
23
- from ..services import RPCMonitor
24
-
25
- logger = get_logger("ipc.monitoring")
26
-
27
-
28
- class RPCMonitorViewSet(viewsets.ViewSet):
29
- """
30
- ViewSet for RPC monitoring and statistics.
31
-
32
- Provides comprehensive monitoring data for the RPC system including:
33
- - Health checks
34
- - Overview statistics
35
- - Recent requests
36
- - Notification stats
37
- - Method-level statistics
38
- """
39
-
40
- authentication_classes = [SessionAuthentication]
41
- permission_classes = [IsAdminUser]
42
-
43
- @extend_schema(
44
- tags=['IPC/RPC Monitoring'],
45
- summary="Get RPC health status",
46
- description="Returns the current health status of the RPC monitoring system.",
47
- responses={
48
- 200: HealthCheckSerializer,
49
- 503: {"description": "Service unavailable"},
50
- },
51
- )
52
- @action(detail=False, methods=['get'], url_path='health')
53
- def health(self, request):
54
- """Get health status of RPC monitoring."""
55
- try:
56
- monitor = RPCMonitor()
57
- health_data = monitor.health_check()
58
-
59
- serializer = HealthCheckSerializer(data=health_data)
60
- serializer.is_valid(raise_exception=True)
61
-
62
- return Response(serializer.validated_data)
63
-
64
- except ConnectionError as e:
65
- logger.error(f"Health check connection error: {e}")
66
- return Response(
67
- {"error": "Redis connection unavailable"},
68
- status=status.HTTP_503_SERVICE_UNAVAILABLE
69
- )
70
- except Exception as e:
71
- logger.error(f"Health check error: {e}", exc_info=True)
72
- return Response(
73
- {"error": "Internal server error"},
74
- status=status.HTTP_500_INTERNAL_SERVER_ERROR
75
- )
76
-
77
- @extend_schema(
78
- tags=['IPC/RPC Monitoring'],
79
- summary="Get overview statistics",
80
- description="Returns overview statistics for RPC monitoring.",
81
- responses={
82
- 200: OverviewStatsSerializer,
83
- 503: {"description": "Service unavailable"},
84
- },
85
- )
86
- @action(detail=False, methods=['get'], url_path='overview')
87
- def overview(self, request):
88
- """Get overview statistics for RPC monitoring."""
89
- try:
90
- monitor = RPCMonitor()
91
- stats_data = monitor.get_overview_stats()
92
-
93
- serializer = OverviewStatsSerializer(data=stats_data)
94
- serializer.is_valid(raise_exception=True)
95
-
96
- return Response(serializer.validated_data)
97
-
98
- except ValueError as e:
99
- logger.warning(f"Overview stats validation error: {e}")
100
- return Response(
101
- {"error": str(e)},
102
- status=status.HTTP_400_BAD_REQUEST
103
- )
104
- except ConnectionError as e:
105
- logger.error(f"Overview stats connection error: {e}")
106
- return Response(
107
- {"error": "Redis connection unavailable"},
108
- status=status.HTTP_503_SERVICE_UNAVAILABLE
109
- )
110
- except Exception as e:
111
- logger.error(f"Overview stats error: {e}", exc_info=True)
112
- return Response(
113
- {"error": "Internal server error"},
114
- status=status.HTTP_500_INTERNAL_SERVER_ERROR
115
- )
116
-
117
- @extend_schema(
118
- tags=['IPC/RPC Monitoring'],
119
- summary="Get recent RPC requests",
120
- description="Returns a list of recent RPC requests with their details.",
121
- parameters=[
122
- OpenApiParameter(
123
- name="count",
124
- type=OpenApiTypes.INT,
125
- location=OpenApiParameter.QUERY,
126
- description="Number of requests to return (default: 50, max: 200)",
127
- required=False,
128
- ),
129
- ],
130
- responses={
131
- 200: RecentRequestsSerializer,
132
- 400: {"description": "Invalid parameters"},
133
- 503: {"description": "Service unavailable"},
134
- },
135
- )
136
- @action(detail=False, methods=['get'], url_path='requests')
137
- def requests(self, request):
138
- """Get recent RPC requests."""
139
- try:
140
- count = int(request.GET.get('count', 50))
141
- count = min(count, 200) # Max 200
142
-
143
- monitor = RPCMonitor()
144
- requests_list = monitor.get_recent_requests(count=count)
145
-
146
- response_data = {
147
- 'requests': requests_list,
148
- 'count': len(requests_list),
149
- 'total_available': monitor.get_total_requests_count()
150
- }
151
-
152
- serializer = RecentRequestsSerializer(data=response_data)
153
- serializer.is_valid(raise_exception=True)
154
-
155
- return Response(serializer.validated_data)
156
-
157
- except ValueError as e:
158
- logger.warning(f"Recent requests validation error: {e}")
159
- return Response(
160
- {"error": "Invalid count parameter"},
161
- status=status.HTTP_400_BAD_REQUEST
162
- )
163
- except ConnectionError as e:
164
- logger.error(f"Recent requests connection error: {e}")
165
- return Response(
166
- {"error": "Redis connection unavailable"},
167
- status=status.HTTP_503_SERVICE_UNAVAILABLE
168
- )
169
- except Exception as e:
170
- logger.error(f"Recent requests error: {e}", exc_info=True)
171
- return Response(
172
- {"error": "Internal server error"},
173
- status=status.HTTP_500_INTERNAL_SERVER_ERROR
174
- )
175
-
176
- @extend_schema(
177
- tags=['IPC/RPC Monitoring'],
178
- summary="Get notification statistics",
179
- description="Returns statistics about RPC notifications.",
180
- responses={
181
- 200: NotificationStatsSerializer,
182
- 503: {"description": "Service unavailable"},
183
- },
184
- )
185
- @action(detail=False, methods=['get'], url_path='notifications')
186
- def notifications(self, request):
187
- """Get notification statistics."""
188
- try:
189
- monitor = RPCMonitor()
190
- stats_data = monitor.get_notification_stats()
191
-
192
- serializer = NotificationStatsSerializer(data=stats_data)
193
- serializer.is_valid(raise_exception=True)
194
-
195
- return Response(serializer.validated_data)
196
-
197
- except ConnectionError as e:
198
- logger.error(f"Notification stats connection error: {e}")
199
- return Response(
200
- {"error": "Redis connection unavailable"},
201
- status=status.HTTP_503_SERVICE_UNAVAILABLE
202
- )
203
- except Exception as e:
204
- logger.error(f"Notification stats error: {e}", exc_info=True)
205
- return Response(
206
- {"error": "Internal server error"},
207
- status=status.HTTP_500_INTERNAL_SERVER_ERROR
208
- )
209
-
210
- @extend_schema(
211
- tags=['IPC/RPC Monitoring'],
212
- summary="Get method statistics",
213
- description="Returns statistics grouped by RPC method.",
214
- responses={
215
- 200: MethodStatsSerializer,
216
- 503: {"description": "Service unavailable"},
217
- },
218
- )
219
- @action(detail=False, methods=['get'], url_path='methods')
220
- def methods(self, request):
221
- """Get statistics grouped by RPC method."""
222
- try:
223
- monitor = RPCMonitor()
224
- methods_list = monitor.get_method_stats()
225
-
226
- # Calculate total calls
227
- total_calls = sum(method.get('count', 0) for method in methods_list)
228
-
229
- response_data = {
230
- 'methods': methods_list,
231
- 'count': len(methods_list),
232
- 'total_calls': total_calls
233
- }
234
-
235
- serializer = MethodStatsSerializer(data=response_data)
236
- serializer.is_valid(raise_exception=True)
237
-
238
- return Response(serializer.validated_data)
239
-
240
- except ConnectionError as e:
241
- logger.error(f"Method stats connection error: {e}")
242
- return Response(
243
- {"error": "Redis connection unavailable"},
244
- status=status.HTTP_503_SERVICE_UNAVAILABLE
245
- )
246
- except Exception as e:
247
- logger.error(f"Method stats error: {e}", exc_info=True)
248
- return Response(
249
- {"error": "Internal server error"},
250
- status=status.HTTP_500_INTERNAL_SERVER_ERROR
251
- )