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,161 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """Hierarchical metrics collector with handler-based output.
3
+
4
+ Example usage::
5
+
6
+ from lmcache.cli.metrics import Metrics
7
+
8
+ metrics = Metrics(title="Bench KV Cache Result (30s)")
9
+
10
+ # Sectioned metrics
11
+ metrics.add_section("ops", "Operations (ops/s)")
12
+ metrics["ops"].add("store", "Store", 41.3)
13
+ metrics["ops"].add("retrieve", "Retrieve", 127.3)
14
+
15
+ # Top-level (flat) metrics
16
+ metrics.add("status", "Status", "OK")
17
+
18
+ metrics.emit()
19
+ """
20
+
21
+ # Standard
22
+ from typing import Any, Optional
23
+
24
+ # First Party
25
+ from lmcache.cli.metrics.handler import FileHandler, MetricsHandler
26
+ from lmcache.cli.metrics.section import Section, sections_to_dict
27
+ from lmcache.logging import init_logger
28
+
29
+ logger = init_logger(__name__)
30
+
31
+
32
+ class Metrics:
33
+ """Hierarchical metrics collector with handler-based output.
34
+
35
+ Handlers are registered via :meth:`add_handler` and triggered
36
+ together by :meth:`emit`. ``BaseCommand`` sets up default
37
+ handlers automatically, so command authors typically only need
38
+ to build metrics and call :meth:`emit`.
39
+
40
+ Args:
41
+ title: Report title shown in the header.
42
+ """
43
+
44
+ def __init__(self, title: str) -> None:
45
+ self._title = title
46
+ self._sections: list[Section] = []
47
+ self._section_map: dict[Optional[str], Section] = {}
48
+ self._handlers: list[MetricsHandler] = []
49
+
50
+ def title(self, title: str) -> None:
51
+ """Set the report title.
52
+
53
+ Args:
54
+ title: New report title shown in the header.
55
+ """
56
+ self._title = title
57
+
58
+ # -- Handler management -------------------------------------------------
59
+
60
+ def add_handler(self, handler: MetricsHandler) -> None:
61
+ """Register a handler.
62
+
63
+ Args:
64
+ handler: The handler to add.
65
+ """
66
+ self._handlers.append(handler)
67
+
68
+ # -- Section management -------------------------------------------------
69
+
70
+ def add_section(self, key: str, label: str) -> Section:
71
+ """Add a named section.
72
+
73
+ Args:
74
+ key: Machine-readable section key (used in JSON output and
75
+ for ``metrics["key"]`` access).
76
+ label: Human-readable label (used in terminal output).
77
+
78
+ Returns:
79
+ The newly created ``Section``.
80
+
81
+ Raises:
82
+ ValueError: If a section with the same *key* already exists.
83
+ """
84
+ if key in self._section_map:
85
+ raise ValueError(f"Section {key!r} already exists")
86
+ section = Section(key, label)
87
+ self._sections.append(section)
88
+ self._section_map[key] = section
89
+ return section
90
+
91
+ def add_list_section(self, group: str, key: str, label: str) -> Section:
92
+ """Add a section that belongs to a list group.
93
+
94
+ In terminal output, renders as a normal section with *label* as
95
+ the header. In JSON output, sections sharing the same *group*
96
+ are collected into a list: ``"group": [{...}, {...}]``.
97
+
98
+ Args:
99
+ group: The JSON key for the list (e.g., ``"models"``).
100
+ key: Unique machine key for this section instance.
101
+ label: Human-readable label (used in terminal output).
102
+
103
+ Returns:
104
+ The newly created ``Section``.
105
+ """
106
+ if key in self._section_map:
107
+ raise ValueError(f"Section {key!r} already exists")
108
+ section = Section(key, label, list_group=group)
109
+ self._sections.append(section)
110
+ self._section_map[key] = section
111
+ return section
112
+
113
+ def __getitem__(self, key: str) -> Section:
114
+ """Return the section registered under *key*.
115
+
116
+ Raises:
117
+ KeyError: If ``add_section(key, ...)`` was not called first.
118
+ """
119
+ return self._section_map[key]
120
+
121
+ # -- Flat (top-level) metrics -------------------------------------------
122
+
123
+ def _default_section(self) -> Section:
124
+ """Return the unnamed default section, creating it on first use."""
125
+ if None not in self._section_map:
126
+ section = Section(None, None)
127
+ # Insert at the beginning so flat metrics appear first
128
+ self._sections.insert(0, section)
129
+ self._section_map[None] = section
130
+ return self._section_map[None]
131
+
132
+ def add(self, key: str, label: str, value: Any) -> None:
133
+ """Record a top-level metric (not inside any named section).
134
+
135
+ Args:
136
+ key: Machine-readable key (used in JSON output).
137
+ label: Human-readable label (used in terminal output).
138
+ value: Metric value.
139
+ """
140
+ self._default_section().add(key, label, value)
141
+
142
+ # -- Output -------------------------------------------------------------
143
+
144
+ def emit(self) -> None:
145
+ """Trigger all registered handlers."""
146
+ for handler in self._handlers:
147
+ handler.emit(self._title, self._sections)
148
+ for handler in self._handlers:
149
+ if isinstance(handler, FileHandler):
150
+ logger.info("Results saved to %s", handler.path)
151
+
152
+ def to_dict(self) -> dict[str, Any]:
153
+ """Return metrics as a JSON-serialisable dictionary.
154
+
155
+ Returns:
156
+ A dict with ``"title"`` and ``"metrics"`` keys. Named
157
+ sections become nested dicts keyed by machine key. The
158
+ unnamed default section's entries are placed at the top
159
+ level of ``"metrics"``.
160
+ """
161
+ return sections_to_dict(self._title, self._sections)
@@ -0,0 +1,77 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """Section — a named group of metric entries."""
3
+
4
+ # Standard
5
+ from typing import Any, Optional
6
+
7
+
8
+ class Section:
9
+ """A named group of metrics.
10
+
11
+ Each entry has a machine ``key`` (used in JSON), a human-readable
12
+ ``label`` (used in terminal output), and a ``value``.
13
+
14
+ Sections with the same :attr:`list_group` are collected into a
15
+ JSON list under that key (e.g., ``"models": [{...}, {...}]``).
16
+ In terminal output they render as normal independent sections.
17
+ """
18
+
19
+ def __init__(
20
+ self,
21
+ key: Optional[str],
22
+ label: Optional[str],
23
+ list_group: Optional[str] = None,
24
+ ) -> None:
25
+ self.key = key
26
+ self.label = label
27
+ self.list_group = list_group
28
+ self.entries: list[tuple[str, str, Any]] = []
29
+
30
+ def add(self, key: str, label: str, value: Any) -> None:
31
+ """Record a metric in this section.
32
+
33
+ Args:
34
+ key: Machine-readable key (used in JSON output).
35
+ label: Human-readable label (used in terminal output).
36
+ value: Metric value. Floats are formatted to 2 decimal
37
+ places on terminal output; strings are printed as-is.
38
+ """
39
+ self.entries.append((key, label, value))
40
+
41
+
42
+ def sections_to_dict(
43
+ title: str,
44
+ sections: list[Section],
45
+ ) -> dict[str, Any]:
46
+ """Convert a title and sections to a JSON-serialisable dictionary.
47
+
48
+ Named sections become nested dicts keyed by machine key. The
49
+ unnamed default section's entries are placed at the top level
50
+ of ``"metrics"``.
51
+
52
+ Args:
53
+ title: The report title.
54
+ sections: Ordered list of ``Section`` objects.
55
+
56
+ Returns:
57
+ A dict with ``"title"`` and ``"metrics"`` keys.
58
+ """
59
+ metrics: dict[str, Any] = {}
60
+ list_groups: dict[str, list[dict[str, Any]]] = {}
61
+ for section in sections:
62
+ if section.key is None:
63
+ for key, _label, value in section.entries:
64
+ metrics[key] = value
65
+ elif section.list_group is not None:
66
+ section_dict: dict[str, Any] = {}
67
+ for key, _label, value in section.entries:
68
+ section_dict[key] = value
69
+ list_groups.setdefault(section.list_group, []).append(section_dict)
70
+ else:
71
+ section_dict = {}
72
+ for key, _label, value in section.entries:
73
+ section_dict[key] = value
74
+ metrics[section.key] = section_dict
75
+ for group_key, items in list_groups.items():
76
+ metrics[group_key] = items
77
+ return {"title": title, "metrics": metrics}
lmcache/connections.py ADDED
@@ -0,0 +1,173 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # This file is copied from the vLLM project (https://github.com/vllm-project/vllm).
3
+ # Original source file: [vllm/vllm/connections.py]
4
+ # License: [Apache License 2.0]
5
+ # Modifications: header name
6
+
7
+ # Standard
8
+ from pathlib import Path
9
+ from typing import Mapping, MutableMapping, Optional
10
+ from urllib.parse import urlparse
11
+
12
+ # Third Party
13
+ import aiohttp
14
+ import requests
15
+
16
+
17
+ class HTTPConnection:
18
+ """Helper class to send HTTP requests."""
19
+
20
+ def __init__(self, *, reuse_client: bool = True) -> None:
21
+ super().__init__()
22
+
23
+ self.reuse_client = reuse_client
24
+
25
+ self._sync_client: Optional[requests.Session] = None
26
+ self._async_client: Optional[aiohttp.ClientSession] = None
27
+
28
+ def get_sync_client(self) -> requests.Session:
29
+ if self._sync_client is None or not self.reuse_client:
30
+ self._sync_client = requests.Session()
31
+
32
+ return self._sync_client
33
+
34
+ # NOTE: We intentionally use an async function even though it is not
35
+ # required, so that the client is only accessible inside async event loop
36
+ async def get_async_client(self) -> aiohttp.ClientSession:
37
+ if self._async_client is None or not self.reuse_client:
38
+ self._async_client = aiohttp.ClientSession()
39
+
40
+ return self._async_client
41
+
42
+ def _validate_http_url(self, url: str):
43
+ parsed_url = urlparse(url)
44
+
45
+ if parsed_url.scheme not in ("http", "https"):
46
+ raise ValueError(
47
+ "Invalid HTTP URL: A valid HTTP URL must have scheme 'http' or 'https'."
48
+ )
49
+
50
+ def _headers(self, **extras: str) -> MutableMapping[str, str]:
51
+ return {"User-Agent": "LMCache", **extras}
52
+
53
+ def get_response(
54
+ self,
55
+ url: str,
56
+ *,
57
+ stream: bool = False,
58
+ timeout: Optional[float] = None,
59
+ extra_headers: Optional[Mapping[str, str]] = None,
60
+ ):
61
+ self._validate_http_url(url)
62
+
63
+ client = self.get_sync_client()
64
+ extra_headers = extra_headers or {}
65
+
66
+ return client.get(
67
+ url,
68
+ headers=self._headers(**extra_headers),
69
+ stream=stream,
70
+ timeout=timeout,
71
+ )
72
+
73
+ async def get_async_response(
74
+ self,
75
+ url: str,
76
+ *,
77
+ timeout: Optional[float] = None,
78
+ extra_headers: Optional[Mapping[str, str]] = None,
79
+ ):
80
+ self._validate_http_url(url)
81
+
82
+ client = await self.get_async_client()
83
+ extra_headers = extra_headers or {}
84
+
85
+ return client.get(url, headers=self._headers(**extra_headers), timeout=timeout)
86
+
87
+ def get_bytes(self, url: str, *, timeout: Optional[float] = None) -> bytes:
88
+ with self.get_response(url, timeout=timeout) as r:
89
+ r.raise_for_status()
90
+
91
+ return r.content
92
+
93
+ async def async_get_bytes(
94
+ self,
95
+ url: str,
96
+ *,
97
+ timeout: Optional[float] = None,
98
+ ) -> bytes:
99
+ async with await self.get_async_response(url, timeout=timeout) as r:
100
+ r.raise_for_status()
101
+
102
+ return await r.read()
103
+
104
+ def get_text(self, url: str, *, timeout: Optional[float] = None) -> str:
105
+ with self.get_response(url, timeout=timeout) as r:
106
+ r.raise_for_status()
107
+
108
+ return r.text
109
+
110
+ async def async_get_text(
111
+ self,
112
+ url: str,
113
+ *,
114
+ timeout: Optional[float] = None,
115
+ ) -> str:
116
+ async with await self.get_async_response(url, timeout=timeout) as r:
117
+ r.raise_for_status()
118
+
119
+ return await r.text()
120
+
121
+ def get_json(self, url: str, *, timeout: Optional[float] = None) -> str:
122
+ with self.get_response(url, timeout=timeout) as r:
123
+ r.raise_for_status()
124
+
125
+ return r.json()
126
+
127
+ async def async_get_json(
128
+ self,
129
+ url: str,
130
+ *,
131
+ timeout: Optional[float] = None,
132
+ ) -> str:
133
+ async with await self.get_async_response(url, timeout=timeout) as r:
134
+ r.raise_for_status()
135
+
136
+ return await r.json()
137
+
138
+ def download_file(
139
+ self,
140
+ url: str,
141
+ save_path: Path,
142
+ *,
143
+ timeout: Optional[float] = None,
144
+ chunk_size: int = 128,
145
+ ) -> Path:
146
+ with self.get_response(url, timeout=timeout) as r:
147
+ r.raise_for_status()
148
+
149
+ with save_path.open("wb") as f:
150
+ for chunk in r.iter_content(chunk_size):
151
+ f.write(chunk)
152
+
153
+ return save_path
154
+
155
+ async def async_download_file(
156
+ self,
157
+ url: str,
158
+ save_path: Path,
159
+ *,
160
+ timeout: Optional[float] = None,
161
+ chunk_size: int = 128,
162
+ ) -> Path:
163
+ async with await self.get_async_response(url, timeout=timeout) as r:
164
+ r.raise_for_status()
165
+
166
+ with save_path.open("wb") as f:
167
+ async for chunk in r.content.iter_chunked(chunk_size):
168
+ f.write(chunk)
169
+
170
+ return save_path
171
+
172
+
173
+ global_http_connection = HTTPConnection()
@@ -0,0 +1,2 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+
@@ -0,0 +1,165 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """
3
+ BaseServiceFactory: Abstract interface for creating LMCache service components.
4
+
5
+ Each serving engine integration (e.g., vLLM) should implement a concrete
6
+ ServiceFactory that determines which components to create for each role.
7
+ """
8
+
9
+ # Standard
10
+ from abc import ABC, abstractmethod
11
+ from typing import TYPE_CHECKING, Optional, Union
12
+
13
+ # First Party
14
+ from lmcache.logging import init_logger
15
+ from lmcache.v1.config import LMCacheEngineConfig
16
+ from lmcache.v1.health_monitor.base import HealthMonitor
17
+ from lmcache.v1.health_monitor.constants import (
18
+ DEFAULT_PING_INTERVAL,
19
+ PING_INTERVAL_CONFIG_KEY,
20
+ )
21
+
22
+ if TYPE_CHECKING:
23
+ # First Party
24
+ from lmcache.observability import PrometheusLogger
25
+ from lmcache.v1.cache_engine import LMCacheEngine
26
+ from lmcache.v1.internal_api_server.api_server import InternalAPIServer
27
+ from lmcache.v1.lookup_client.abstract_client import LookupClientInterface
28
+ from lmcache.v1.lookup_client.lmcache_async_lookup_client import (
29
+ LMCacheAsyncLookupServer,
30
+ )
31
+ from lmcache.v1.lookup_client.lmcache_lookup_client import LMCacheLookupServer
32
+ from lmcache.v1.manager import LMCacheManager
33
+ from lmcache.v1.metadata import LMCacheMetadata
34
+ from lmcache.v1.offload_server.zmq_server import ZMQOffloadServer
35
+ from lmcache.v1.plugin.runtime_plugin_launcher import RuntimePluginLauncher
36
+
37
+ logger = init_logger(__name__)
38
+
39
+
40
+ class BaseServiceFactory(ABC):
41
+ """Abstract base for creating LMCache service components.
42
+
43
+ Subclasses must implement all methods to provide the appropriate
44
+ components for their serving engine integration.
45
+ """
46
+
47
+ @abstractmethod
48
+ def get_engine_instance_id(self) -> str:
49
+ """Return the instance_id used to register the engine with
50
+ LMCacheEngineBuilder. Used by LMCacheManager for engine destruction."""
51
+ raise NotImplementedError
52
+
53
+ @abstractmethod
54
+ def get_or_create_metadata(self) -> Optional["LMCacheMetadata"]:
55
+ raise NotImplementedError
56
+
57
+ @abstractmethod
58
+ def get_or_create_lmcache_engine(self) -> Optional["LMCacheEngine"]:
59
+ raise NotImplementedError
60
+
61
+ @abstractmethod
62
+ def maybe_create_lookup_client(self) -> Optional["LookupClientInterface"]:
63
+ raise NotImplementedError
64
+
65
+ @abstractmethod
66
+ def maybe_create_prometheus_logger(self) -> Optional["PrometheusLogger"]:
67
+ raise NotImplementedError
68
+
69
+ @abstractmethod
70
+ def maybe_create_lookup_server(
71
+ self,
72
+ ) -> Optional[Union["LMCacheLookupServer", "LMCacheAsyncLookupServer"]]:
73
+ raise NotImplementedError
74
+
75
+ @abstractmethod
76
+ def maybe_create_offload_server(self) -> Optional["ZMQOffloadServer"]:
77
+ raise NotImplementedError
78
+
79
+ @abstractmethod
80
+ def maybe_create_runtime_plugin_launcher(
81
+ self,
82
+ ) -> Optional["RuntimePluginLauncher"]:
83
+ raise NotImplementedError
84
+
85
+ @abstractmethod
86
+ def maybe_create_internal_api_server(
87
+ self, lmcache_manager: "LMCacheManager"
88
+ ) -> Optional["InternalAPIServer"]:
89
+ raise NotImplementedError
90
+
91
+ @abstractmethod
92
+ def maybe_create_health_monitor(
93
+ self, lmcache_manager: "LMCacheManager"
94
+ ) -> Optional[HealthMonitor]:
95
+ raise NotImplementedError
96
+
97
+ def _create_health_monitor(
98
+ self,
99
+ lmcache_manager: "LMCacheManager",
100
+ config: LMCacheEngineConfig,
101
+ engine: Optional["LMCacheEngine"] = None,
102
+ ) -> HealthMonitor:
103
+ """Create, configure, and start the health monitor.
104
+
105
+ Shared implementation used by subclass maybe_create_health_monitor.
106
+ """
107
+ # First Party
108
+ from lmcache.observability import PrometheusLogger
109
+ from lmcache.v1.periodic_thread import (
110
+ PeriodicThreadRegistry,
111
+ ThreadLevel,
112
+ )
113
+
114
+ ping_interval = config.get_extra_config_value(
115
+ PING_INTERVAL_CONFIG_KEY, DEFAULT_PING_INTERVAL
116
+ )
117
+ health_monitor = HealthMonitor(
118
+ manager=lmcache_manager,
119
+ ping_interval=ping_interval,
120
+ )
121
+
122
+ if engine is not None:
123
+ engine.set_health_monitor(health_monitor)
124
+
125
+ health_monitor.start()
126
+ logger.info("Health monitor initialized and started")
127
+
128
+ prometheus_logger = PrometheusLogger.GetInstanceOrNone()
129
+ if prometheus_logger is not None:
130
+ prometheus_logger.lmcache_is_healthy.set_function(
131
+ lambda: 1 if lmcache_manager.is_healthy() else 0
132
+ )
133
+
134
+ registry = PeriodicThreadRegistry.get_instance()
135
+
136
+ prometheus_logger.periodic_threads_total_count.set_function(
137
+ lambda: len(registry.get_all())
138
+ )
139
+ prometheus_logger.periodic_threads_running_count.set_function(
140
+ lambda: registry.get_running_count()
141
+ )
142
+ prometheus_logger.periodic_threads_active_count.set_function(
143
+ lambda: registry.get_active_count()
144
+ )
145
+
146
+ for level in ThreadLevel:
147
+ level_name = level.value
148
+ total_attr = f"periodic_threads_{level_name}_total"
149
+ running_attr = f"periodic_threads_{level_name}_running"
150
+ active_attr = f"periodic_threads_{level_name}_active"
151
+
152
+ if hasattr(prometheus_logger, total_attr):
153
+ getattr(prometheus_logger, total_attr).set_function(
154
+ lambda lvl=level: registry.get_count_by_level(lvl)["total"]
155
+ )
156
+ if hasattr(prometheus_logger, running_attr):
157
+ getattr(prometheus_logger, running_attr).set_function(
158
+ lambda lvl=level: registry.get_count_by_level(lvl)["running"]
159
+ )
160
+ if hasattr(prometheus_logger, active_attr):
161
+ getattr(prometheus_logger, active_attr).set_function(
162
+ lambda lvl=level: registry.get_count_by_level(lvl)["active"]
163
+ )
164
+
165
+ return health_monitor
@@ -0,0 +1 @@
1
+ # SPDX-License-Identifier: Apache-2.0
@@ -0,0 +1,51 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """
3
+ Abstract base class for request telemetry.
4
+
5
+ This module provides the interface for tracking request-level events
6
+ in LMCache, such as when a request finishes and its associated async
7
+ save operations complete.
8
+ """
9
+
10
+ # Standard
11
+ from abc import ABC, abstractmethod
12
+ from typing import Any
13
+
14
+
15
+ class RequestTelemetry(ABC):
16
+ """
17
+ Abstract base class for request telemetry.
18
+
19
+ This class defines the interface for capturing request-level telemetry
20
+ events. Implementations can log events, emit metrics, or perform other
21
+ actions when specific request lifecycle events occur.
22
+ """
23
+
24
+ @abstractmethod
25
+ def __init__(self, config: dict[str, Any]) -> None:
26
+ pass
27
+
28
+ @abstractmethod
29
+ def on_request_store_finished(
30
+ self,
31
+ request_ids_set: set[str],
32
+ model_name: str,
33
+ world_size: int,
34
+ kv_rank: int,
35
+ ) -> None:
36
+ """
37
+ Callback when request finishes AND all its KV cache store ops completes.
38
+
39
+ This method ensures that request_ids_set is not empty.
40
+
41
+ Technically this function is implemented by inspecting the return value
42
+ of `get_finished` method.
43
+ """
44
+ pass
45
+
46
+ @abstractmethod
47
+ def close(self) -> None:
48
+ pass
49
+
50
+ def __del__(self) -> None:
51
+ self.close()