system_router.py 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. import textwrap
  2. from datetime import datetime, timezone
  3. from typing import Optional
  4. import psutil
  5. from fastapi import Depends, Query
  6. from core.base import R2RException
  7. from core.base.api.models import (
  8. GenericMessageResponse,
  9. WrappedGenericMessageResponse,
  10. WrappedLogsResponse,
  11. WrappedServerStatsResponse,
  12. WrappedSettingsResponse,
  13. )
  14. from ...abstractions import R2RProviders, R2RServices
  15. from .base_router import BaseRouterV3
  16. class SystemRouter(BaseRouterV3):
  17. def __init__(
  18. self,
  19. providers: R2RProviders,
  20. services: R2RServices,
  21. ):
  22. super().__init__(providers, services)
  23. self.start_time = datetime.now(timezone.utc)
  24. def _setup_routes(self):
  25. @self.router.get(
  26. "/health",
  27. # dependencies=[Depends(self.rate_limit_dependency)],
  28. openapi_extra={
  29. "x-codeSamples": [
  30. {
  31. "lang": "Python",
  32. "source": textwrap.dedent(
  33. """
  34. from r2r import R2RClient
  35. client = R2RClient()
  36. # when using auth, do client.login(...)
  37. result = client.system.health()
  38. """
  39. ),
  40. },
  41. {
  42. "lang": "JavaScript",
  43. "source": textwrap.dedent(
  44. """
  45. const { r2rClient } = require("r2r-js");
  46. const client = new r2rClient();
  47. function main() {
  48. const response = await client.system.health();
  49. }
  50. main();
  51. """
  52. ),
  53. },
  54. {
  55. "lang": "CLI",
  56. "source": textwrap.dedent(
  57. """
  58. r2r health
  59. """
  60. ),
  61. },
  62. {
  63. "lang": "cURL",
  64. "source": textwrap.dedent(
  65. """
  66. curl -X POST "https://api.example.com/v3/health"\\
  67. -H "Content-Type: application/json" \\
  68. -H "Authorization: Bearer YOUR_API_KEY" \\
  69. """
  70. ),
  71. },
  72. ]
  73. },
  74. )
  75. @self.base_endpoint
  76. async def health_check() -> WrappedGenericMessageResponse:
  77. return GenericMessageResponse(message="ok") # type: ignore
  78. @self.router.get(
  79. "/system/settings",
  80. dependencies=[Depends(self.rate_limit_dependency)],
  81. openapi_extra={
  82. "x-codeSamples": [
  83. {
  84. "lang": "Python",
  85. "source": textwrap.dedent(
  86. """
  87. from r2r import R2RClient
  88. client = R2RClient()
  89. # when using auth, do client.login(...)
  90. result = client.system.settings()
  91. """
  92. ),
  93. },
  94. {
  95. "lang": "JavaScript",
  96. "source": textwrap.dedent(
  97. """
  98. const { r2rClient } = require("r2r-js");
  99. const client = new r2rClient();
  100. function main() {
  101. const response = await client.system.settings();
  102. }
  103. main();
  104. """
  105. ),
  106. },
  107. {
  108. "lang": "CLI",
  109. "source": textwrap.dedent(
  110. """
  111. r2r system settings
  112. """
  113. ),
  114. },
  115. {
  116. "lang": "cURL",
  117. "source": textwrap.dedent(
  118. """
  119. curl -X POST "https://api.example.com/v3/system/settings" \\
  120. -H "Content-Type: application/json" \\
  121. -H "Authorization: Bearer YOUR_API_KEY" \\
  122. """
  123. ),
  124. },
  125. ]
  126. },
  127. )
  128. @self.base_endpoint
  129. async def app_settings(
  130. auth_user=Depends(self.providers.auth.auth_wrapper()),
  131. ) -> WrappedSettingsResponse:
  132. if not auth_user.is_superuser:
  133. raise R2RException(
  134. "Only a superuser can call the `system/settings` endpoint.",
  135. 403,
  136. )
  137. return await self.services.management.app_settings()
  138. @self.router.get(
  139. "/system/status",
  140. dependencies=[Depends(self.rate_limit_dependency)],
  141. openapi_extra={
  142. "x-codeSamples": [
  143. {
  144. "lang": "Python",
  145. "source": textwrap.dedent(
  146. """
  147. from r2r import R2RClient
  148. client = R2RClient()
  149. # when using auth, do client.login(...)
  150. result = client.system.status()
  151. """
  152. ),
  153. },
  154. {
  155. "lang": "JavaScript",
  156. "source": textwrap.dedent(
  157. """
  158. const { r2rClient } = require("r2r-js");
  159. const client = new r2rClient();
  160. function main() {
  161. const response = await client.system.status();
  162. }
  163. main();
  164. """
  165. ),
  166. },
  167. {
  168. "lang": "CLI",
  169. "source": textwrap.dedent(
  170. """
  171. r2r system status
  172. """
  173. ),
  174. },
  175. {
  176. "lang": "cURL",
  177. "source": textwrap.dedent(
  178. """
  179. curl -X POST "https://api.example.com/v3/system/status" \\
  180. -H "Content-Type: application/json" \\
  181. -H "Authorization: Bearer YOUR_API_KEY" \\
  182. """
  183. ),
  184. },
  185. ]
  186. },
  187. )
  188. @self.base_endpoint
  189. async def server_stats(
  190. auth_user=Depends(self.providers.auth.auth_wrapper()),
  191. ) -> WrappedServerStatsResponse:
  192. if not auth_user.is_superuser:
  193. raise R2RException(
  194. "Only an authorized user can call the `system/status` endpoint.",
  195. 403,
  196. )
  197. return { # type: ignore
  198. "start_time": self.start_time.isoformat(),
  199. "uptime_seconds": (
  200. datetime.now(timezone.utc) - self.start_time
  201. ).total_seconds(),
  202. "cpu_usage": psutil.cpu_percent(),
  203. "memory_usage": psutil.virtual_memory().percent,
  204. }