lmcache-cli 0.4.5.dev0__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.
Files changed (399) hide show
  1. lmcache/__init__.py +84 -0
  2. lmcache/_version.py +24 -0
  3. lmcache/cli/__init__.py +1 -0
  4. lmcache/cli/commands/__init__.py +34 -0
  5. lmcache/cli/commands/base.py +157 -0
  6. lmcache/cli/commands/bench/__init__.py +557 -0
  7. lmcache/cli/commands/bench/engine_bench/__init__.py +1 -0
  8. lmcache/cli/commands/bench/engine_bench/config.py +245 -0
  9. lmcache/cli/commands/bench/engine_bench/interactive/__init__.py +274 -0
  10. lmcache/cli/commands/bench/engine_bench/interactive/config.json +10 -0
  11. lmcache/cli/commands/bench/engine_bench/interactive/schema.py +352 -0
  12. lmcache/cli/commands/bench/engine_bench/interactive/state.py +327 -0
  13. lmcache/cli/commands/bench/engine_bench/interactive/terminal.py +291 -0
  14. lmcache/cli/commands/bench/engine_bench/progress.py +145 -0
  15. lmcache/cli/commands/bench/engine_bench/request_sender.py +232 -0
  16. lmcache/cli/commands/bench/engine_bench/stats.py +275 -0
  17. lmcache/cli/commands/bench/engine_bench/workloads/__init__.py +153 -0
  18. lmcache/cli/commands/bench/engine_bench/workloads/base.py +122 -0
  19. lmcache/cli/commands/bench/engine_bench/workloads/long_doc_permutator.py +435 -0
  20. lmcache/cli/commands/bench/engine_bench/workloads/long_doc_qa.py +281 -0
  21. lmcache/cli/commands/bench/engine_bench/workloads/multi_round_chat.py +337 -0
  22. lmcache/cli/commands/bench/engine_bench/workloads/random_prefill.py +178 -0
  23. lmcache/cli/commands/describe.py +310 -0
  24. lmcache/cli/commands/kvcache.py +133 -0
  25. lmcache/cli/commands/mock.py +75 -0
  26. lmcache/cli/commands/ping.py +113 -0
  27. lmcache/cli/commands/query/__init__.py +155 -0
  28. lmcache/cli/commands/query/prompt.py +134 -0
  29. lmcache/cli/commands/query/request.py +357 -0
  30. lmcache/cli/commands/server.py +99 -0
  31. lmcache/cli/commands/tool/__init__.py +63 -0
  32. lmcache/cli/commands/tool/cache_simulator.py +113 -0
  33. lmcache/cli/commands/trace/__init__.py +505 -0
  34. lmcache/cli/commands/trace/dispatch.py +249 -0
  35. lmcache/cli/commands/trace/driver.py +372 -0
  36. lmcache/cli/commands/trace/stats.py +289 -0
  37. lmcache/cli/documents/lmcache.txt +11 -0
  38. lmcache/cli/main.py +42 -0
  39. lmcache/cli/metrics/__init__.py +29 -0
  40. lmcache/cli/metrics/formatter.py +171 -0
  41. lmcache/cli/metrics/handler.py +94 -0
  42. lmcache/cli/metrics/metrics.py +161 -0
  43. lmcache/cli/metrics/section.py +77 -0
  44. lmcache/connections.py +173 -0
  45. lmcache/integration/__init__.py +2 -0
  46. lmcache/integration/base_service_factory.py +165 -0
  47. lmcache/integration/request_telemetry/__init__.py +1 -0
  48. lmcache/integration/request_telemetry/base.py +51 -0
  49. lmcache/integration/request_telemetry/factory.py +113 -0
  50. lmcache/integration/request_telemetry/fastapi.py +109 -0
  51. lmcache/integration/request_telemetry/noop.py +35 -0
  52. lmcache/integration/sglang/__init__.py +2 -0
  53. lmcache/integration/sglang/sglang_adapter.py +326 -0
  54. lmcache/integration/sglang/utils.py +39 -0
  55. lmcache/integration/vllm/__init__.py +1 -0
  56. lmcache/integration/vllm/lmcache_connector_v1.py +213 -0
  57. lmcache/integration/vllm/lmcache_connector_v1_085.py +150 -0
  58. lmcache/integration/vllm/lmcache_mp_connector_0180.py +1072 -0
  59. lmcache/integration/vllm/tests/test_mm_hash_utils.py +112 -0
  60. lmcache/integration/vllm/utils.py +433 -0
  61. lmcache/integration/vllm/vllm_multi_process_adapter.py +1090 -0
  62. lmcache/integration/vllm/vllm_service_factory.py +339 -0
  63. lmcache/integration/vllm/vllm_v1_adapter.py +1713 -0
  64. lmcache/logging.py +107 -0
  65. lmcache/native_storage_ops.pyi +230 -0
  66. lmcache/non_cuda_equivalents.py +1424 -0
  67. lmcache/observability.py +1958 -0
  68. lmcache/storage_backend/serde/__init__.py +1 -0
  69. lmcache/storage_backend/serde/cachegen_basics.py +210 -0
  70. lmcache/storage_backend/serde/cachegen_decoder.py +207 -0
  71. lmcache/storage_backend/serde/cachegen_encoder.py +394 -0
  72. lmcache/storage_backend/serde/serde.py +75 -0
  73. lmcache/tools/__init__.py +1 -0
  74. lmcache/tools/cache_simulator/README.md +392 -0
  75. lmcache/tools/cache_simulator/__init__.py +1 -0
  76. lmcache/tools/cache_simulator/docs/simulate_example.png +0 -0
  77. lmcache/tools/cache_simulator/docs/sweep_example.png +0 -0
  78. lmcache/tools/cache_simulator/gen_bench_dataset.py +360 -0
  79. lmcache/tools/cache_simulator/lru_cache.py +124 -0
  80. lmcache/tools/cache_simulator/plot_hit_rate.py +231 -0
  81. lmcache/tools/cache_simulator/simulator.py +795 -0
  82. lmcache/tools/controller_benchmark/README.md +161 -0
  83. lmcache/tools/controller_benchmark/__init__.py +1 -0
  84. lmcache/tools/controller_benchmark/__main__.py +331 -0
  85. lmcache/tools/controller_benchmark/benchmark.py +660 -0
  86. lmcache/tools/controller_benchmark/config.py +44 -0
  87. lmcache/tools/controller_benchmark/constants.py +10 -0
  88. lmcache/tools/controller_benchmark/handlers/__init__.py +46 -0
  89. lmcache/tools/controller_benchmark/handlers/admit.py +52 -0
  90. lmcache/tools/controller_benchmark/handlers/base.py +47 -0
  91. lmcache/tools/controller_benchmark/handlers/deregister.py +49 -0
  92. lmcache/tools/controller_benchmark/handlers/evict.py +52 -0
  93. lmcache/tools/controller_benchmark/handlers/heartbeat.py +56 -0
  94. lmcache/tools/controller_benchmark/handlers/p2p_lookup.py +47 -0
  95. lmcache/tools/controller_benchmark/handlers/register.py +56 -0
  96. lmcache/tools/mp_status_viewer/__init__.py +1 -0
  97. lmcache/tools/mp_status_viewer/__main__.py +95 -0
  98. lmcache/usage_context.py +417 -0
  99. lmcache/utils.py +665 -0
  100. lmcache/v1/__init__.py +2 -0
  101. lmcache/v1/api_server/__init__.py +2 -0
  102. lmcache/v1/api_server/__main__.py +537 -0
  103. lmcache/v1/basic_check.py +112 -0
  104. lmcache/v1/cache_controller/__init__.py +9 -0
  105. lmcache/v1/cache_controller/commands/__init__.py +15 -0
  106. lmcache/v1/cache_controller/commands/base.py +35 -0
  107. lmcache/v1/cache_controller/commands/full_sync.py +49 -0
  108. lmcache/v1/cache_controller/config.py +176 -0
  109. lmcache/v1/cache_controller/controller_manager.py +535 -0
  110. lmcache/v1/cache_controller/controllers/__init__.py +11 -0
  111. lmcache/v1/cache_controller/controllers/full_sync_tracker.py +473 -0
  112. lmcache/v1/cache_controller/controllers/kv_controller.py +439 -0
  113. lmcache/v1/cache_controller/controllers/registration_controller.py +282 -0
  114. lmcache/v1/cache_controller/executor.py +463 -0
  115. lmcache/v1/cache_controller/frontend/static/css/style.css +201 -0
  116. lmcache/v1/cache_controller/frontend/static/img/logo.png +0 -0
  117. lmcache/v1/cache_controller/frontend/static/index.html +234 -0
  118. lmcache/v1/cache_controller/frontend/static/js/controller_app.js +660 -0
  119. lmcache/v1/cache_controller/full_sync_sender.py +475 -0
  120. lmcache/v1/cache_controller/locks.py +149 -0
  121. lmcache/v1/cache_controller/message.py +828 -0
  122. lmcache/v1/cache_controller/observability.py +208 -0
  123. lmcache/v1/cache_controller/utils.py +679 -0
  124. lmcache/v1/cache_controller/worker.py +665 -0
  125. lmcache/v1/cache_engine.py +2058 -0
  126. lmcache/v1/cache_interface.py +19 -0
  127. lmcache/v1/check/__init__.py +74 -0
  128. lmcache/v1/check/check_mode_gen.py +86 -0
  129. lmcache/v1/check/check_mode_test_l2_adapter.py +284 -0
  130. lmcache/v1/check/check_mode_test_remote.py +155 -0
  131. lmcache/v1/check/check_mode_test_storage_manager.py +142 -0
  132. lmcache/v1/check/utils.py +571 -0
  133. lmcache/v1/compute/__init__.py +2 -0
  134. lmcache/v1/compute/attention/__init__.py +0 -0
  135. lmcache/v1/compute/attention/abstract.py +39 -0
  136. lmcache/v1/compute/attention/flash_attn.py +129 -0
  137. lmcache/v1/compute/attention/flash_infer_sparse.py +284 -0
  138. lmcache/v1/compute/attention/metadata.py +85 -0
  139. lmcache/v1/compute/attention/utils.py +14 -0
  140. lmcache/v1/compute/blend/__init__.py +7 -0
  141. lmcache/v1/compute/blend/blender.py +168 -0
  142. lmcache/v1/compute/blend/metadata.py +34 -0
  143. lmcache/v1/compute/blend/utils.py +63 -0
  144. lmcache/v1/compute/models/__init__.py +0 -0
  145. lmcache/v1/compute/models/base.py +141 -0
  146. lmcache/v1/compute/models/llama.py +9 -0
  147. lmcache/v1/compute/models/qwen3.py +24 -0
  148. lmcache/v1/compute/models/utils.py +68 -0
  149. lmcache/v1/compute/positional_encoding.py +199 -0
  150. lmcache/v1/config.py +848 -0
  151. lmcache/v1/config_base.py +848 -0
  152. lmcache/v1/distributed/api.py +248 -0
  153. lmcache/v1/distributed/config.py +321 -0
  154. lmcache/v1/distributed/error.py +64 -0
  155. lmcache/v1/distributed/eviction.py +192 -0
  156. lmcache/v1/distributed/eviction_policy/__init__.py +21 -0
  157. lmcache/v1/distributed/eviction_policy/factory.py +27 -0
  158. lmcache/v1/distributed/eviction_policy/lru.py +244 -0
  159. lmcache/v1/distributed/eviction_policy/noop.py +50 -0
  160. lmcache/v1/distributed/internal_api.py +170 -0
  161. lmcache/v1/distributed/l1_manager.py +835 -0
  162. lmcache/v1/distributed/l2_adapters/__init__.py +67 -0
  163. lmcache/v1/distributed/l2_adapters/base.py +360 -0
  164. lmcache/v1/distributed/l2_adapters/config.py +385 -0
  165. lmcache/v1/distributed/l2_adapters/factory.py +205 -0
  166. lmcache/v1/distributed/l2_adapters/fs_l2_adapter.py +747 -0
  167. lmcache/v1/distributed/l2_adapters/fs_native_l2_adapter.py +167 -0
  168. lmcache/v1/distributed/l2_adapters/mock_l2_adapter.py +516 -0
  169. lmcache/v1/distributed/l2_adapters/mooncake_store_l2_adapter.py +135 -0
  170. lmcache/v1/distributed/l2_adapters/native_connector_l2_adapter.py +468 -0
  171. lmcache/v1/distributed/l2_adapters/native_plugin_l2_adapter.py +199 -0
  172. lmcache/v1/distributed/l2_adapters/nixl_store_dynamic_l2_adapter.py +831 -0
  173. lmcache/v1/distributed/l2_adapters/nixl_store_l2_adapter.py +983 -0
  174. lmcache/v1/distributed/l2_adapters/plugin_l2_adapter.py +210 -0
  175. lmcache/v1/distributed/l2_adapters/resp_l2_adapter.py +176 -0
  176. lmcache/v1/distributed/memory_manager.py +179 -0
  177. lmcache/v1/distributed/storage_controller.py +39 -0
  178. lmcache/v1/distributed/storage_controllers/__init__.py +43 -0
  179. lmcache/v1/distributed/storage_controllers/eviction_controller.py +242 -0
  180. lmcache/v1/distributed/storage_controllers/prefetch_controller.py +830 -0
  181. lmcache/v1/distributed/storage_controllers/prefetch_policy.py +193 -0
  182. lmcache/v1/distributed/storage_controllers/store_controller.py +452 -0
  183. lmcache/v1/distributed/storage_controllers/store_policy.py +213 -0
  184. lmcache/v1/distributed/storage_manager.py +532 -0
  185. lmcache/v1/event_manager.py +145 -0
  186. lmcache/v1/exceptions/__init__.py +16 -0
  187. lmcache/v1/gpu_connector/__init__.py +126 -0
  188. lmcache/v1/gpu_connector/gpu_connectors.py +1906 -0
  189. lmcache/v1/gpu_connector/gpu_ops.py +85 -0
  190. lmcache/v1/gpu_connector/hpu_connector.py +326 -0
  191. lmcache/v1/gpu_connector/mock_gpu_connector.py +67 -0
  192. lmcache/v1/gpu_connector/utils.py +890 -0
  193. lmcache/v1/gpu_connector/xpu_connectors.py +916 -0
  194. lmcache/v1/health_monitor/__init__.py +1 -0
  195. lmcache/v1/health_monitor/base.py +587 -0
  196. lmcache/v1/health_monitor/checks/__init__.py +1 -0
  197. lmcache/v1/health_monitor/checks/remote_backend_check.py +304 -0
  198. lmcache/v1/health_monitor/constants.py +36 -0
  199. lmcache/v1/internal_api_server/__init__.py +0 -0
  200. lmcache/v1/internal_api_server/api_registry.py +59 -0
  201. lmcache/v1/internal_api_server/api_server.py +120 -0
  202. lmcache/v1/internal_api_server/common/__init__.py +1 -0
  203. lmcache/v1/internal_api_server/common/env_api.py +22 -0
  204. lmcache/v1/internal_api_server/common/loglevel_api.py +57 -0
  205. lmcache/v1/internal_api_server/common/metrics_api.py +29 -0
  206. lmcache/v1/internal_api_server/common/periodic_thread_api.py +138 -0
  207. lmcache/v1/internal_api_server/common/run_script_api.py +73 -0
  208. lmcache/v1/internal_api_server/common/thread_api.py +63 -0
  209. lmcache/v1/internal_api_server/controller/__init__.py +1 -0
  210. lmcache/v1/internal_api_server/controller/key_stats_api.py +81 -0
  211. lmcache/v1/internal_api_server/controller/worker_info_api.py +136 -0
  212. lmcache/v1/internal_api_server/utils.py +43 -0
  213. lmcache/v1/internal_api_server/vllm/__init__.py +1 -0
  214. lmcache/v1/internal_api_server/vllm/backend_api.py +221 -0
  215. lmcache/v1/internal_api_server/vllm/bypass_api.py +204 -0
  216. lmcache/v1/internal_api_server/vllm/cache_api.py +895 -0
  217. lmcache/v1/internal_api_server/vllm/chunk_statistics_api.py +141 -0
  218. lmcache/v1/internal_api_server/vllm/conf_api.py +147 -0
  219. lmcache/v1/internal_api_server/vllm/freeze_api.py +172 -0
  220. lmcache/v1/internal_api_server/vllm/hot_cache_api.py +184 -0
  221. lmcache/v1/internal_api_server/vllm/inference_api.py +65 -0
  222. lmcache/v1/internal_api_server/vllm/load_fs_chunks_api.py +320 -0
  223. lmcache/v1/internal_api_server/vllm/lookup_api.py +145 -0
  224. lmcache/v1/internal_api_server/vllm/version_api.py +25 -0
  225. lmcache/v1/kv_layer_groups.py +267 -0
  226. lmcache/v1/lazy_memory_allocator.py +284 -0
  227. lmcache/v1/lookup_client/__init__.py +25 -0
  228. lmcache/v1/lookup_client/abstract_client.py +77 -0
  229. lmcache/v1/lookup_client/async_lookup_message.py +50 -0
  230. lmcache/v1/lookup_client/chunk_statistics_lookup_client.py +200 -0
  231. lmcache/v1/lookup_client/factory.py +251 -0
  232. lmcache/v1/lookup_client/hit_limit_lookup_client.py +86 -0
  233. lmcache/v1/lookup_client/lmcache_async_lookup_client.py +407 -0
  234. lmcache/v1/lookup_client/lmcache_lookup_client.py +285 -0
  235. lmcache/v1/lookup_client/lmcache_lookup_client_bypass.py +99 -0
  236. lmcache/v1/lookup_client/mooncake_lookup_client.py +87 -0
  237. lmcache/v1/lookup_client/record_strategies/__init__.py +77 -0
  238. lmcache/v1/lookup_client/record_strategies/base.py +327 -0
  239. lmcache/v1/lookup_client/record_strategies/file_hash.py +130 -0
  240. lmcache/v1/lookup_client/record_strategies/memory_bloom_filter.py +81 -0
  241. lmcache/v1/manager.py +539 -0
  242. lmcache/v1/memory_management.py +2619 -0
  243. lmcache/v1/metadata.py +114 -0
  244. lmcache/v1/mp_observability/AGENTS.override.md +21 -0
  245. lmcache/v1/mp_observability/README.md +204 -0
  246. lmcache/v1/mp_observability/config.py +340 -0
  247. lmcache/v1/mp_observability/event.py +100 -0
  248. lmcache/v1/mp_observability/event_bus.py +313 -0
  249. lmcache/v1/mp_observability/otel_init.py +145 -0
  250. lmcache/v1/mp_observability/subscribers/__init__.py +28 -0
  251. lmcache/v1/mp_observability/subscribers/logging/__init__.py +19 -0
  252. lmcache/v1/mp_observability/subscribers/logging/l1.py +56 -0
  253. lmcache/v1/mp_observability/subscribers/logging/l2.py +73 -0
  254. lmcache/v1/mp_observability/subscribers/logging/lookup_hash.py +209 -0
  255. lmcache/v1/mp_observability/subscribers/logging/mp_server.py +90 -0
  256. lmcache/v1/mp_observability/subscribers/logging/sm.py +59 -0
  257. lmcache/v1/mp_observability/subscribers/metrics/__init__.py +20 -0
  258. lmcache/v1/mp_observability/subscribers/metrics/l0_lifecycle.py +290 -0
  259. lmcache/v1/mp_observability/subscribers/metrics/l1.py +55 -0
  260. lmcache/v1/mp_observability/subscribers/metrics/l1_lifecycle.py +166 -0
  261. lmcache/v1/mp_observability/subscribers/metrics/l2.py +121 -0
  262. lmcache/v1/mp_observability/subscribers/metrics/sm.py +69 -0
  263. lmcache/v1/mp_observability/subscribers/tracing/__init__.py +12 -0
  264. lmcache/v1/mp_observability/subscribers/tracing/mp_server.py +333 -0
  265. lmcache/v1/mp_observability/subscribers/tracing/span_registry.py +148 -0
  266. lmcache/v1/mp_observability/trace/__init__.py +50 -0
  267. lmcache/v1/mp_observability/trace/codecs.py +255 -0
  268. lmcache/v1/mp_observability/trace/decorator.py +147 -0
  269. lmcache/v1/mp_observability/trace/format.py +132 -0
  270. lmcache/v1/mp_observability/trace/lifecycle.py +83 -0
  271. lmcache/v1/mp_observability/trace/reader.py +167 -0
  272. lmcache/v1/mp_observability/trace/recorder.py +300 -0
  273. lmcache/v1/multiprocess/__init__.py +0 -0
  274. lmcache/v1/multiprocess/affinity_pool.py +102 -0
  275. lmcache/v1/multiprocess/blend_server_v2.py +891 -0
  276. lmcache/v1/multiprocess/config.py +253 -0
  277. lmcache/v1/multiprocess/custom_types.py +281 -0
  278. lmcache/v1/multiprocess/futures.py +194 -0
  279. lmcache/v1/multiprocess/gpu_context.py +511 -0
  280. lmcache/v1/multiprocess/http_server.py +235 -0
  281. lmcache/v1/multiprocess/mp_runtime_plugin_launcher.py +130 -0
  282. lmcache/v1/multiprocess/mq.py +732 -0
  283. lmcache/v1/multiprocess/protocol.py +86 -0
  284. lmcache/v1/multiprocess/protocols/README.md +213 -0
  285. lmcache/v1/multiprocess/protocols/__init__.py +127 -0
  286. lmcache/v1/multiprocess/protocols/base.py +89 -0
  287. lmcache/v1/multiprocess/protocols/blend.py +109 -0
  288. lmcache/v1/multiprocess/protocols/blend_v2.py +57 -0
  289. lmcache/v1/multiprocess/protocols/controller.py +53 -0
  290. lmcache/v1/multiprocess/protocols/debug.py +34 -0
  291. lmcache/v1/multiprocess/protocols/engine.py +146 -0
  292. lmcache/v1/multiprocess/protocols/observability.py +39 -0
  293. lmcache/v1/multiprocess/server.py +1134 -0
  294. lmcache/v1/multiprocess/session.py +190 -0
  295. lmcache/v1/multiprocess/token_hasher.py +441 -0
  296. lmcache/v1/offload_server/__init__.py +17 -0
  297. lmcache/v1/offload_server/abstract_server.py +37 -0
  298. lmcache/v1/offload_server/message.py +30 -0
  299. lmcache/v1/offload_server/zmq_server.py +122 -0
  300. lmcache/v1/periodic_thread.py +579 -0
  301. lmcache/v1/pin_monitor.py +246 -0
  302. lmcache/v1/plugin/__init__.py +0 -0
  303. lmcache/v1/plugin/runtime_plugin_launcher.py +211 -0
  304. lmcache/v1/protocol.py +317 -0
  305. lmcache/v1/rpc/__init__.py +17 -0
  306. lmcache/v1/rpc/transport.py +105 -0
  307. lmcache/v1/rpc/zmq_transport.py +213 -0
  308. lmcache/v1/rpc_utils.py +165 -0
  309. lmcache/v1/server/__init__.py +2 -0
  310. lmcache/v1/server/__main__.py +170 -0
  311. lmcache/v1/server/storage_backend/__init__.py +21 -0
  312. lmcache/v1/server/storage_backend/abstract_backend.py +80 -0
  313. lmcache/v1/server/storage_backend/local_backend.py +75 -0
  314. lmcache/v1/server/utils.py +21 -0
  315. lmcache/v1/standalone/__init__.py +1 -0
  316. lmcache/v1/standalone/__main__.py +583 -0
  317. lmcache/v1/standalone/manager.py +80 -0
  318. lmcache/v1/standalone/standalone_service_factory.py +86 -0
  319. lmcache/v1/storage_backend/__init__.py +313 -0
  320. lmcache/v1/storage_backend/abstract_backend.py +445 -0
  321. lmcache/v1/storage_backend/audit_backend.py +233 -0
  322. lmcache/v1/storage_backend/batched_message_sender.py +222 -0
  323. lmcache/v1/storage_backend/cache_policy/__init__.py +45 -0
  324. lmcache/v1/storage_backend/cache_policy/base_policy.py +87 -0
  325. lmcache/v1/storage_backend/cache_policy/fifo.py +58 -0
  326. lmcache/v1/storage_backend/cache_policy/lfu.py +105 -0
  327. lmcache/v1/storage_backend/cache_policy/lru.py +81 -0
  328. lmcache/v1/storage_backend/cache_policy/mru.py +61 -0
  329. lmcache/v1/storage_backend/connector/__init__.py +443 -0
  330. lmcache/v1/storage_backend/connector/audit_adapter.py +77 -0
  331. lmcache/v1/storage_backend/connector/audit_connector.py +320 -0
  332. lmcache/v1/storage_backend/connector/base_connector.py +379 -0
  333. lmcache/v1/storage_backend/connector/blackhole_adapter.py +21 -0
  334. lmcache/v1/storage_backend/connector/blackhole_connector.py +37 -0
  335. lmcache/v1/storage_backend/connector/eic_adapter.py +31 -0
  336. lmcache/v1/storage_backend/connector/eic_connector.py +757 -0
  337. lmcache/v1/storage_backend/connector/external_adapter.py +79 -0
  338. lmcache/v1/storage_backend/connector/fs_adapter.py +51 -0
  339. lmcache/v1/storage_backend/connector/fs_connector.py +403 -0
  340. lmcache/v1/storage_backend/connector/infinistore_adapter.py +56 -0
  341. lmcache/v1/storage_backend/connector/infinistore_connector.py +177 -0
  342. lmcache/v1/storage_backend/connector/instrumented_connector.py +219 -0
  343. lmcache/v1/storage_backend/connector/lm_adapter.py +31 -0
  344. lmcache/v1/storage_backend/connector/lm_connector.py +176 -0
  345. lmcache/v1/storage_backend/connector/mock_adapter.py +57 -0
  346. lmcache/v1/storage_backend/connector/mock_connector.py +349 -0
  347. lmcache/v1/storage_backend/connector/mooncakestore_adapter.py +43 -0
  348. lmcache/v1/storage_backend/connector/mooncakestore_connector.py +614 -0
  349. lmcache/v1/storage_backend/connector/redis_adapter.py +181 -0
  350. lmcache/v1/storage_backend/connector/redis_connector.py +828 -0
  351. lmcache/v1/storage_backend/connector/s3_adapter.py +59 -0
  352. lmcache/v1/storage_backend/connector/s3_connector.py +699 -0
  353. lmcache/v1/storage_backend/connector/sagemaker_hyperpod_adapter.py +233 -0
  354. lmcache/v1/storage_backend/connector/sagemaker_hyperpod_connector.py +987 -0
  355. lmcache/v1/storage_backend/connector/valkey_adapter.py +114 -0
  356. lmcache/v1/storage_backend/connector/valkey_connector.py +627 -0
  357. lmcache/v1/storage_backend/gds_backend.py +1199 -0
  358. lmcache/v1/storage_backend/job_executor/__init__.py +0 -0
  359. lmcache/v1/storage_backend/job_executor/base_executor.py +34 -0
  360. lmcache/v1/storage_backend/job_executor/pq_executor.py +235 -0
  361. lmcache/v1/storage_backend/local_cpu_backend.py +810 -0
  362. lmcache/v1/storage_backend/local_disk_backend.py +656 -0
  363. lmcache/v1/storage_backend/maru_backend.py +734 -0
  364. lmcache/v1/storage_backend/naive_serde/__init__.py +50 -0
  365. lmcache/v1/storage_backend/naive_serde/cachegen_basics.py +133 -0
  366. lmcache/v1/storage_backend/naive_serde/cachegen_decoder.py +135 -0
  367. lmcache/v1/storage_backend/naive_serde/cachegen_encoder.py +83 -0
  368. lmcache/v1/storage_backend/naive_serde/kivi_serde.py +22 -0
  369. lmcache/v1/storage_backend/naive_serde/naive_serde.py +18 -0
  370. lmcache/v1/storage_backend/naive_serde/serde.py +37 -0
  371. lmcache/v1/storage_backend/native_clients/connector_client_base.py +165 -0
  372. lmcache/v1/storage_backend/native_clients/resp_client.py +35 -0
  373. lmcache/v1/storage_backend/nixl_storage_backend.py +1400 -0
  374. lmcache/v1/storage_backend/p2p_backend.py +788 -0
  375. lmcache/v1/storage_backend/path_sharder.py +117 -0
  376. lmcache/v1/storage_backend/pd_backend.py +646 -0
  377. lmcache/v1/storage_backend/plugins/dax_backend.py +1443 -0
  378. lmcache/v1/storage_backend/plugins/rust_raw_block_backend.py +1361 -0
  379. lmcache/v1/storage_backend/remote_backend.py +624 -0
  380. lmcache/v1/storage_backend/resp_client.py +227 -0
  381. lmcache/v1/storage_backend/storage_backend_listener.py +19 -0
  382. lmcache/v1/storage_backend/storage_manager.py +1352 -0
  383. lmcache/v1/system_detection.py +110 -0
  384. lmcache/v1/token_database.py +551 -0
  385. lmcache/v1/transfer_channel/__init__.py +83 -0
  386. lmcache/v1/transfer_channel/abstract.py +285 -0
  387. lmcache/v1/transfer_channel/mock_memory_channel.py +156 -0
  388. lmcache/v1/transfer_channel/nixl_channel.py +639 -0
  389. lmcache/v1/transfer_channel/py_socket_channel.py +260 -0
  390. lmcache/v1/transfer_channel/transfer_utils.py +63 -0
  391. lmcache/v1/utils/__init__.py +1 -0
  392. lmcache/v1/utils/bloom_filter.py +109 -0
  393. lmcache/v1/utils/cache_utils.py +125 -0
  394. lmcache_cli-0.4.5.dev0.dist-info/METADATA +185 -0
  395. lmcache_cli-0.4.5.dev0.dist-info/RECORD +399 -0
  396. lmcache_cli-0.4.5.dev0.dist-info/WHEEL +5 -0
  397. lmcache_cli-0.4.5.dev0.dist-info/entry_points.txt +2 -0
  398. lmcache_cli-0.4.5.dev0.dist-info/licenses/LICENSE +201 -0
  399. lmcache_cli-0.4.5.dev0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,304 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """
3
+ Health check for RemoteBackend.
4
+ """
5
+
6
+ # Standard
7
+ from contextlib import contextmanager
8
+ from typing import TYPE_CHECKING, List, Optional
9
+ import asyncio
10
+ import time
11
+
12
+ # Third Party
13
+ import torch
14
+
15
+ # First Party
16
+ from lmcache.logging import init_logger
17
+ from lmcache.observability import LMCStatsMonitor
18
+ from lmcache.utils import CacheEngineKey
19
+ from lmcache.v1.health_monitor.base import HealthCheck
20
+ from lmcache.v1.health_monitor.constants import (
21
+ DEFAULT_FALLBACK_POLICY,
22
+ DEFAULT_GET_BLOCKING_FAILED_THRESHOLD,
23
+ DEFAULT_PING_TIMEOUT,
24
+ DEFAULT_WAITING_TIME_FOR_RECOVERY,
25
+ FALLBACK_POLICY_CONFIG_KEY,
26
+ GET_BLOCKING_FAILED_THRESHOLD_CONFIG_KEY,
27
+ PING_GENERIC_ERROR_CODE,
28
+ PING_TIMEOUT_CONFIG_KEY,
29
+ PING_TIMEOUT_ERROR_CODE,
30
+ WAITING_TIME_FOR_RECOVERY_CONFIG_KEY,
31
+ FallbackPolicy,
32
+ )
33
+ from lmcache.v1.storage_backend.connector import InstrumentedRemoteConnector
34
+ from lmcache.v1.storage_backend.connector.audit_connector import AuditConnector
35
+
36
+ if TYPE_CHECKING:
37
+ # First Party
38
+ from lmcache.v1.manager import LMCacheManager
39
+ from lmcache.v1.storage_backend.remote_backend import RemoteBackend
40
+
41
+ logger = init_logger(__name__)
42
+
43
+
44
+ class RemoteBackendHealthCheck(HealthCheck):
45
+ """
46
+ Health check for RemoteBackend by pinging the remote connector.
47
+
48
+ This check verifies that the remote backend is reachable and responsive
49
+ by sending periodic ping requests.
50
+
51
+ Fallback Policies:
52
+ - RECOMPUTE (default): Skip all cache operations when
53
+ remote backend is unhealthy
54
+ - LOCAL_CPU: Bypass remote backend and use local CPU with hot_cache enabled
55
+ """
56
+
57
+ def __init__(
58
+ self,
59
+ backend: "RemoteBackend",
60
+ ):
61
+ self.backend = backend
62
+ # Get fallback policy from config
63
+ fallback_policy_str = backend.config.get_extra_config_value(
64
+ FALLBACK_POLICY_CONFIG_KEY, DEFAULT_FALLBACK_POLICY.value
65
+ )
66
+ # Convert string to FallbackPolicy enum
67
+ if isinstance(fallback_policy_str, str):
68
+ try:
69
+ self._fallback_policy = FallbackPolicy(fallback_policy_str)
70
+ except ValueError:
71
+ logger.warning(
72
+ f"Invalid fallback_policy '{fallback_policy_str}' "
73
+ f"for {backend}, using default: "
74
+ f"{DEFAULT_FALLBACK_POLICY}"
75
+ )
76
+ self._fallback_policy = DEFAULT_FALLBACK_POLICY
77
+ elif isinstance(fallback_policy_str, FallbackPolicy):
78
+ self._fallback_policy = fallback_policy_str
79
+ self.failure_time: Optional[float] = None
80
+ self._stats_monitor = LMCStatsMonitor.GetOrCreate()
81
+ self._backend_name: Optional[str] = None
82
+ self._last_get_blocking_failed_count = 0
83
+
84
+ @classmethod
85
+ def create(cls, manager: "LMCacheManager") -> List[HealthCheck]:
86
+ """
87
+ Create RemoteBackendHealthCheck instances from a LMCacheManager.
88
+
89
+ This method finds all RemoteBackend instances in the storage manager
90
+ and creates a health check for each one.
91
+
92
+ Args:
93
+ manager: The LMCacheManager instance
94
+
95
+ Returns:
96
+ List of RemoteBackendHealthCheck instances
97
+ """
98
+ # Import here to avoid circular imports
99
+ # First Party
100
+ from lmcache.v1.storage_backend.remote_backend import RemoteBackend
101
+
102
+ instances: List[HealthCheck] = []
103
+
104
+ # Get engine from manager
105
+ engine = manager.lmcache_engine
106
+ if engine is None or engine.storage_manager is None:
107
+ return instances
108
+
109
+ for backend_name, backend in engine.storage_manager.storage_backends.items():
110
+ if isinstance(backend, RemoteBackend):
111
+ check = cls(backend)
112
+ check._backend_name = backend_name
113
+ instances.append(check)
114
+ logger.info(f"Created {check} for {backend_name}")
115
+
116
+ return instances
117
+
118
+ def name(self) -> str:
119
+ return f"RemoteBackendHealthCheck({self.backend.remote_url})"
120
+
121
+ @property
122
+ def fallback_policy(self) -> FallbackPolicy:
123
+ """Return the fallback policy for this health check."""
124
+ return self._fallback_policy
125
+
126
+ def get_bypass_backend_name(self) -> Optional[str]:
127
+ """
128
+ Return the backend name to bypass when this health check fails.
129
+
130
+ Returns:
131
+ Optional[str]: The backend name (e.g., "RemoteBackend")
132
+ """
133
+ return self._backend_name
134
+
135
+ def _get_ping_timeout(self) -> float:
136
+ """Get the ping timeout from the backend config."""
137
+ return self.backend.config.get_extra_config_value(
138
+ PING_TIMEOUT_CONFIG_KEY, DEFAULT_PING_TIMEOUT
139
+ )
140
+
141
+ def _try_reinitialize_connection(self) -> bool:
142
+ """
143
+ Try to reinitialize the connection if connector is None.
144
+
145
+ Returns:
146
+ bool: True if connection was successfully initialized, False otherwise
147
+ """
148
+ if self.backend.connection is not None:
149
+ return True
150
+
151
+ logger.warning("Connector is None, re-initializing connection.")
152
+ self.backend.init_connection()
153
+
154
+ return self.backend.connection is not None
155
+
156
+ def check(self) -> bool:
157
+ """
158
+ Perform a health check on remote backend, which includes the following checks:
159
+
160
+ - get_blocking/batched_get_blocking, if failed count >= threshold,
161
+ which means check failed, update failure_time and return False.
162
+ If failure_time is not None, wait for more than`waiting_time_for_recovery`
163
+ seconds before resuming the check.
164
+
165
+ - ping, if connector supports ping, send a ping request to remote connector.
166
+
167
+ Returns:
168
+ bool: True if all checks succeeds, False otherwise
169
+ """
170
+ # Try to reinitialize connection if needed
171
+ if not self._try_reinitialize_connection():
172
+ return False
173
+
174
+ # At this point, connector is guaranteed to be not None
175
+ connector = self.backend.connection
176
+ assert connector is not None
177
+
178
+ if self.failure_time is not None:
179
+ waiting_time = self.backend.config.get_extra_config_value(
180
+ WAITING_TIME_FOR_RECOVERY_CONFIG_KEY,
181
+ DEFAULT_WAITING_TIME_FOR_RECOVERY,
182
+ )
183
+ if (
184
+ time.time() - self.failure_time > waiting_time
185
+ and self._put_and_get_check()
186
+ ):
187
+ # recover from get blocking failed
188
+ logger.info(
189
+ "Failure time: %s, current time: %s, "
190
+ "recover from get blocking failed",
191
+ self.failure_time,
192
+ time.time(),
193
+ )
194
+ self.failure_time = None
195
+ else:
196
+ logger.info(
197
+ "Failure time: %s, current time: %s, "
198
+ "still in get blocking failed recovery window",
199
+ self.failure_time,
200
+ time.time(),
201
+ )
202
+ return False
203
+
204
+ # Check read failed
205
+ current_get_blocking_failed_count = self.backend.get_blocking_failed_count
206
+ get_blocking_failed_count = (
207
+ current_get_blocking_failed_count - self._last_get_blocking_failed_count
208
+ )
209
+ self._last_get_blocking_failed_count = current_get_blocking_failed_count
210
+ threshold = self.backend.config.get_extra_config_value(
211
+ GET_BLOCKING_FAILED_THRESHOLD_CONFIG_KEY,
212
+ DEFAULT_GET_BLOCKING_FAILED_THRESHOLD,
213
+ )
214
+ if get_blocking_failed_count >= threshold:
215
+ logger.warning(
216
+ "Detected %s get blocking failed in interval, threshold: %s",
217
+ get_blocking_failed_count,
218
+ threshold,
219
+ )
220
+ self.failure_time = time.time()
221
+ return False
222
+
223
+ # If connector doesn't support ping, assume it's healthy
224
+ if not connector.support_ping():
225
+ return True
226
+
227
+ # Check ping
228
+ try:
229
+ start_time = time.perf_counter()
230
+ future = asyncio.run_coroutine_threadsafe(
231
+ connector.ping(), self.backend.loop
232
+ )
233
+ error_code = future.result(timeout=self._get_ping_timeout())
234
+ latency = (time.perf_counter() - start_time) * 1000
235
+
236
+ # Record ping latency
237
+ self._stats_monitor.update_remote_ping_latency(latency)
238
+ # Record error code (0 means success)
239
+ self._stats_monitor.update_remote_ping_error_code(error_code)
240
+
241
+ if error_code != 0:
242
+ logger.warning(f"Ping failed with error code: {error_code}")
243
+ return False
244
+
245
+ return True
246
+
247
+ except asyncio.TimeoutError:
248
+ logger.warning("Ping timeout")
249
+ self._stats_monitor.update_remote_ping_error_code(PING_TIMEOUT_ERROR_CODE)
250
+ return False
251
+ except Exception as e:
252
+ logger.error(f"Ping error: {e}")
253
+ self._stats_monitor.update_remote_ping_error_code(PING_GENERIC_ERROR_CODE)
254
+ return False
255
+
256
+ def _put_and_get_check(self) -> bool:
257
+ if self.backend.local_cpu_backend is None or self.backend.connection is None:
258
+ return False
259
+
260
+ with self._resource_manager() as (put_obj, get_obj):
261
+ if put_obj is None:
262
+ return False
263
+ if get_obj is None:
264
+ logger.warning("Get failed, the return value is None, check failed.")
265
+ return False
266
+ return torch.equal(put_obj.raw_tensor, get_obj.raw_tensor)
267
+
268
+ @contextmanager
269
+ def _resource_manager(self):
270
+ key = CacheEngineKey(
271
+ model_name="test",
272
+ world_size=1,
273
+ worker_id=0,
274
+ chunk_hash=0,
275
+ dtype=torch.bfloat16,
276
+ )
277
+ connector = self.backend.connection
278
+ if isinstance(connector, InstrumentedRemoteConnector):
279
+ connector = connector.getWrappedConnector()
280
+ if isinstance(connector, AuditConnector):
281
+ connector = connector.real_connector
282
+ shapes = connector.meta_shapes
283
+ dtypes = connector.meta_dtypes
284
+ fmt = connector.meta_fmt
285
+ put_obj, get_obj = None, None
286
+ try:
287
+ # put
288
+ put_obj = self.backend.local_cpu_backend.allocate(shapes, dtypes, fmt)
289
+ future = self.backend.submit_put_task(key, put_obj)
290
+ future.result(timeout=self._get_ping_timeout())
291
+ # get
292
+ get_obj = self.backend.get_blocking(key)
293
+ yield put_obj, get_obj
294
+ except asyncio.TimeoutError:
295
+ logger.warning("Put timeout, check failed.")
296
+ yield None, None
297
+ except Exception as e:
298
+ logger.error(f"Put error, check failed: {e}")
299
+ yield None, None
300
+ finally:
301
+ if put_obj is not None:
302
+ put_obj.ref_count_down()
303
+ if get_obj is not None:
304
+ get_obj.ref_count_down()
@@ -0,0 +1,36 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """
3
+ Constants for health monitoring.
4
+ """
5
+
6
+ # Standard
7
+ from enum import Enum
8
+
9
+
10
+ class FallbackPolicy(str, Enum):
11
+ """Fallback policy when health check fails."""
12
+
13
+ RECOMPUTE = "recompute" # Skip all cache operations, fall back to recomputation
14
+ LOCAL_CPU = "local_cpu" # Fall back to local CPU backend only
15
+
16
+
17
+ # Ping error codes
18
+ PING_TIMEOUT_ERROR_CODE = -1
19
+ PING_GENERIC_ERROR_CODE = -2
20
+
21
+ # Configuration keys
22
+ PING_TIMEOUT_CONFIG_KEY = "ping_timeout"
23
+ PING_INTERVAL_CONFIG_KEY = "ping_interval"
24
+ FALLBACK_POLICY_CONFIG_KEY = "fallback_policy"
25
+ GET_BLOCKING_FAILED_THRESHOLD_CONFIG_KEY = "get_blocking_failed_threshold"
26
+ WAITING_TIME_FOR_RECOVERY_CONFIG_KEY = "waiting_time_for_recovery"
27
+
28
+ # Default values
29
+ DEFAULT_PING_TIMEOUT = 5.0
30
+ DEFAULT_PING_INTERVAL = 30.0
31
+ DEFAULT_FALLBACK_POLICY = FallbackPolicy.RECOMPUTE
32
+ DEFAULT_GET_BLOCKING_FAILED_THRESHOLD = 10
33
+ DEFAULT_WAITING_TIME_FOR_RECOVERY = 300.0
34
+
35
+ # Memory thresholds
36
+ DEFAULT_MEMORY_THRESHOLD_PERCENT = 95.0 # Unhealthy if memory usage > 95%
File without changes
@@ -0,0 +1,59 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Standard
3
+ from pathlib import Path
4
+ from typing import List, Literal, Optional
5
+ import importlib.util
6
+ import pkgutil
7
+
8
+ # Third Party
9
+ from fastapi import APIRouter
10
+
11
+ APICategory = Literal["common", "vllm", "controller"]
12
+
13
+
14
+ class APIRegistry:
15
+ """
16
+ Automatically discovers and registers API routes by category
17
+
18
+ Categories:
19
+ - common: APIs that work for all components (metrics, logs, etc.)
20
+ - vllm: APIs specific to vLLM scheduler/worker
21
+ - controller: APIs specific to LMCache controller
22
+ """
23
+
24
+ def __init__(self, app):
25
+ self.app = app
26
+ self.router = APIRouter()
27
+
28
+ def register_all_apis(self, categories: Optional[List[APICategory]] = None):
29
+ """
30
+ Discover and register API modules from specified categories
31
+
32
+ Args:
33
+ categories: List of categories to register.
34
+ If None, registers all categories.
35
+ """
36
+ if categories is None:
37
+ categories = ["common", "vllm", "controller"]
38
+
39
+ package_path = Path(__file__).parent
40
+ package_name = __package__
41
+
42
+ for category in categories:
43
+ category_path = package_path / category
44
+ if not category_path.exists():
45
+ continue
46
+
47
+ category_package = f"{package_name}.{category}"
48
+
49
+ for _, module_name, _ in pkgutil.iter_modules([str(category_path)]):
50
+ if module_name.endswith("_api"):
51
+ full_module_name = f"{category_package}.{module_name}"
52
+ module = importlib.import_module(full_module_name)
53
+ # Include the router if it exists
54
+ if hasattr(module, "router") and isinstance(
55
+ module.router, APIRouter
56
+ ):
57
+ self.router.include_router(module.router)
58
+
59
+ self.app.include_router(self.router)
@@ -0,0 +1,120 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Standard
3
+ from typing import TYPE_CHECKING
4
+ import asyncio
5
+ import os
6
+ import threading
7
+
8
+ # Third Party
9
+ from fastapi import FastAPI
10
+ import uvicorn
11
+
12
+ # First Party
13
+ from lmcache.logging import init_logger
14
+
15
+ # Local
16
+ from .api_registry import APIRegistry
17
+
18
+ if TYPE_CHECKING:
19
+ # First Party
20
+ from lmcache.v1.manager import LMCacheManager
21
+
22
+ logger = init_logger(__name__)
23
+
24
+ app = FastAPI()
25
+
26
+ # Automatically register common, vllm, and controller APIs
27
+ registry = APIRegistry(app)
28
+ registry.register_all_apis(categories=["common", "vllm", "controller"])
29
+
30
+
31
+ class InternalAPIServer:
32
+ def __init__(self, lmcache_manager: "LMCacheManager"):
33
+ lmcache_engine = lmcache_manager.lmcache_engine
34
+
35
+ # Check if lmcache_engine is None and handle accordingly
36
+ if lmcache_engine is None:
37
+ # Use manager's config directly when engine is not available
38
+ config = lmcache_manager.config
39
+ port_offset = 0 # Default for scheduler mode
40
+ else:
41
+ config = lmcache_engine.config
42
+ # 0 for scheduler, 1 for worker 0, 2 for worker 1, ...
43
+ port_offset = 1 + lmcache_engine.metadata.worker_id
44
+
45
+ self.port = config.internal_api_server_port_start + port_offset
46
+ self.socket_path_prefix = config.internal_api_server_socket_path_prefix
47
+ self.socket_path = (
48
+ f"{self.socket_path_prefix}_{self.port}"
49
+ if self.socket_path_prefix
50
+ else None
51
+ )
52
+ include_index_list = config.internal_api_server_include_index_list
53
+
54
+ self.enable = True
55
+ if not config.internal_api_server_enabled or (
56
+ include_index_list and port_offset not in include_index_list
57
+ ):
58
+ logger.info(
59
+ f"Internal API server disabled. internal_api_server_enabled="
60
+ f"{config.internal_api_server_enabled}, port_offset={port_offset}, "
61
+ f"port={self.port}, socket_path={self.socket_path}, "
62
+ f"include_index_list={include_index_list}"
63
+ )
64
+ self.enable = False
65
+ return
66
+
67
+ uvicorn_config = {
68
+ "app": app,
69
+ "host": config.internal_api_server_host,
70
+ "loop": "uvloop",
71
+ "http": "httptools",
72
+ "access_log": config.get_extra_config_value(
73
+ "internal_api_server_access_log", True
74
+ ),
75
+ "log_level": config.get_extra_config_value(
76
+ "internal_api_server_log_level", "warning"
77
+ ),
78
+ }
79
+
80
+ if self.socket_path:
81
+ self.server_log_info = f"socket {self.socket_path}"
82
+ logger.info(f"Init internal API server on {self.server_log_info}")
83
+ uvicorn_config["uds"] = self.socket_path
84
+ # Ensure socket directory exists
85
+ os.makedirs(os.path.dirname(self.socket_path), exist_ok=True)
86
+ # Remove existing socket file if exists
87
+ if os.path.exists(self.socket_path):
88
+ os.unlink(self.socket_path)
89
+ else:
90
+ self.server_log_info = f"port {self.port}"
91
+ logger.info(f"Init internal API server on {self.server_log_info}")
92
+ uvicorn_config["port"] = self.port
93
+
94
+ self.server = uvicorn.Server(uvicorn.Config(**uvicorn_config))
95
+ app.state.lmcache_adapter = lmcache_manager
96
+
97
+ async def run(self):
98
+ logger.info(f"Running LMCache internal API server on {self.server_log_info}")
99
+ if self.server:
100
+ await self.server.serve()
101
+
102
+ def start(self):
103
+ if not self.enable:
104
+ return
105
+ logger.info(f"Starting LMCache internal API server on {self.server_log_info}")
106
+ threading.Thread(
107
+ target=asyncio.run,
108
+ args=(self.run(),),
109
+ daemon=True,
110
+ name="api-server-thread",
111
+ ).start()
112
+
113
+ def stop(self):
114
+ if not self.enable:
115
+ return
116
+ logger.info("Stopping LMCache internal API server")
117
+ if self.server:
118
+ self.server.should_exit = True
119
+ if self.socket_path and os.path.exists(self.socket_path):
120
+ os.unlink(self.socket_path)
@@ -0,0 +1 @@
1
+ # SPDX-License-Identifier: Apache-2.0
@@ -0,0 +1,22 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Standard
3
+ import json
4
+ import os
5
+
6
+ # Third Party
7
+ from fastapi import APIRouter
8
+ from starlette.responses import PlainTextResponse
9
+
10
+ router = APIRouter()
11
+
12
+
13
+ @router.get("/env")
14
+ async def get_env():
15
+ """
16
+ Get all environment variables
17
+ """
18
+ env_dict = dict(os.environ)
19
+ return PlainTextResponse(
20
+ content=json.dumps(env_dict, indent=2, sort_keys=True),
21
+ media_type="text/plain",
22
+ )
@@ -0,0 +1,57 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Standard
3
+ from typing import Optional
4
+ import logging
5
+
6
+ # Third Party
7
+ from fastapi import APIRouter
8
+ from starlette.responses import PlainTextResponse
9
+
10
+ router = APIRouter()
11
+
12
+
13
+ @router.get("/loglevel")
14
+ async def get_or_set_log_level(
15
+ logger_name: Optional[str] = None, level: Optional[str] = None
16
+ ):
17
+ """
18
+ Get or set the log level for a logger.
19
+ - No parameters: List all loggers and their levels.
20
+ - With logger_name: Get the level of the specified logger.
21
+ - With logger_name and level: Set the level of the specified logger.
22
+ """
23
+ if not logger_name and not level:
24
+ # List all loggers and their levels
25
+ loggers = logging.Logger.manager.loggerDict
26
+ result = "=== Loggers and Levels ===\n"
27
+ for name, logger_obj in loggers.items():
28
+ if isinstance(logger_obj, logging.Logger):
29
+ result += f"{name}: {logging.getLevelName(logger_obj.level)}\n"
30
+ return PlainTextResponse(content=result, media_type="text/plain")
31
+ elif logger_name and not level:
32
+ # Get the level of the specified logger
33
+ target_logger = logging.getLogger(logger_name)
34
+ return PlainTextResponse(
35
+ content=f"{logger_name}: {logging.getLevelName(target_logger.level)}",
36
+ media_type="text/plain",
37
+ )
38
+ elif logger_name and level:
39
+ # Set the level of the specified logger
40
+ target_logger = logging.getLogger(logger_name)
41
+ try:
42
+ level_value = getattr(logging, level.upper())
43
+ target_logger.setLevel(level_value)
44
+ # Set the level of all handlers
45
+ for handler in target_logger.handlers:
46
+ handler.setLevel(level_value)
47
+ return PlainTextResponse(
48
+ content=f"Set {logger_name} level to {level.upper()} "
49
+ "(including all handlers)",
50
+ media_type="text/plain",
51
+ )
52
+ except AttributeError:
53
+ return PlainTextResponse(
54
+ content=f"Invalid log level: {level}",
55
+ media_type="text/plain",
56
+ status_code=400,
57
+ )
@@ -0,0 +1,29 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Third Party
3
+ from fastapi import APIRouter
4
+ from prometheus_client import REGISTRY, generate_latest
5
+ from starlette.requests import Request
6
+ from starlette.responses import PlainTextResponse
7
+
8
+ # First Party
9
+ from lmcache.observability import reset_observability_metrics
10
+
11
+ router = APIRouter()
12
+
13
+
14
+ @router.get("/metrics")
15
+ async def get_metrics(request: Request):
16
+ """
17
+ Provide Prometheus metrics data
18
+ """
19
+ metrics_data = generate_latest(REGISTRY)
20
+ return PlainTextResponse(content=metrics_data, media_type="text/plain")
21
+
22
+
23
+ @router.post("/metrics/reset")
24
+ async def reset_metrics():
25
+ """
26
+ Reset Prometheus metrics to their initial state.
27
+ """
28
+ reset_observability_metrics()
29
+ return PlainTextResponse(content="ok", media_type="text/plain")