micromegas 0.11.0__py3-none-any.whl → 0.13.0__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 (218) hide show
  1. micromegas/__init__.py +12 -3
  2. micromegas/admin.py +227 -0
  3. micromegas/flightsql/FlightSql_pb2.py +148 -140
  4. micromegas/flightsql/__init__.py +1 -0
  5. micromegas/flightsql/client.py +609 -7
  6. micromegas/flightsql/time.py +1 -0
  7. micromegas/perfetto.py +100 -187
  8. micromegas/time.py +97 -1
  9. micromegas-0.13.0.dist-info/METADATA +120 -0
  10. micromegas-0.13.0.dist-info/RECORD +11 -0
  11. micromegas/thirdparty/perfetto/protos/perfetto/common/android_energy_consumer_descriptor_pb2.py +0 -38
  12. micromegas/thirdparty/perfetto/protos/perfetto/common/android_log_constants_pb2.py +0 -38
  13. micromegas/thirdparty/perfetto/protos/perfetto/common/builtin_clock_pb2.py +0 -36
  14. micromegas/thirdparty/perfetto/protos/perfetto/common/descriptor_pb2.py +0 -62
  15. micromegas/thirdparty/perfetto/protos/perfetto/common/gpu_counter_descriptor_pb2.py +0 -44
  16. micromegas/thirdparty/perfetto/protos/perfetto/common/perf_events_pb2.py +0 -46
  17. micromegas/thirdparty/perfetto/protos/perfetto/common/protolog_common_pb2.py +0 -36
  18. micromegas/thirdparty/perfetto/protos/perfetto/common/sys_stats_counters_pb2.py +0 -38
  19. micromegas/thirdparty/perfetto/protos/perfetto/common/trace_stats_pb2.py +0 -48
  20. micromegas/thirdparty/perfetto/protos/perfetto/config/android/android_game_intervention_list_config_pb2.py +0 -36
  21. micromegas/thirdparty/perfetto/protos/perfetto/config/android/android_input_event_config_pb2.py +0 -42
  22. micromegas/thirdparty/perfetto/protos/perfetto/config/android/android_log_config_pb2.py +0 -37
  23. micromegas/thirdparty/perfetto/protos/perfetto/config/android/android_polled_state_config_pb2.py +0 -36
  24. micromegas/thirdparty/perfetto/protos/perfetto/config/android/android_sdk_sysprop_guard_config_pb2.py +0 -36
  25. micromegas/thirdparty/perfetto/protos/perfetto/config/android/android_system_property_config_pb2.py +0 -36
  26. micromegas/thirdparty/perfetto/protos/perfetto/config/android/network_trace_config_pb2.py +0 -36
  27. micromegas/thirdparty/perfetto/protos/perfetto/config/android/packages_list_config_pb2.py +0 -36
  28. micromegas/thirdparty/perfetto/protos/perfetto/config/android/pixel_modem_config_pb2.py +0 -38
  29. micromegas/thirdparty/perfetto/protos/perfetto/config/android/protolog_config_pb2.py +0 -41
  30. micromegas/thirdparty/perfetto/protos/perfetto/config/android/surfaceflinger_layers_config_pb2.py +0 -40
  31. micromegas/thirdparty/perfetto/protos/perfetto/config/android/surfaceflinger_transactions_config_pb2.py +0 -38
  32. micromegas/thirdparty/perfetto/protos/perfetto/config/chrome/chrome_config_pb2.py +0 -38
  33. micromegas/thirdparty/perfetto/protos/perfetto/config/chrome/v8_config_pb2.py +0 -36
  34. micromegas/thirdparty/perfetto/protos/perfetto/config/data_source_config_pb2.py +0 -120
  35. micromegas/thirdparty/perfetto/protos/perfetto/config/etw/etw_config_pb2.py +0 -38
  36. micromegas/thirdparty/perfetto/protos/perfetto/config/ftrace/ftrace_config_pb2.py +0 -48
  37. micromegas/thirdparty/perfetto/protos/perfetto/config/gpu/gpu_counter_config_pb2.py +0 -36
  38. micromegas/thirdparty/perfetto/protos/perfetto/config/gpu/vulkan_memory_config_pb2.py +0 -36
  39. micromegas/thirdparty/perfetto/protos/perfetto/config/inode_file/inode_file_config_pb2.py +0 -38
  40. micromegas/thirdparty/perfetto/protos/perfetto/config/interceptor_config_pb2.py +0 -37
  41. micromegas/thirdparty/perfetto/protos/perfetto/config/interceptors/console_config_pb2.py +0 -38
  42. micromegas/thirdparty/perfetto/protos/perfetto/config/power/android_power_config_pb2.py +0 -38
  43. micromegas/thirdparty/perfetto/protos/perfetto/config/process_stats/process_stats_config_pb2.py +0 -40
  44. micromegas/thirdparty/perfetto/protos/perfetto/config/profiling/heapprofd_config_pb2.py +0 -38
  45. micromegas/thirdparty/perfetto/protos/perfetto/config/profiling/java_hprof_config_pb2.py +0 -38
  46. micromegas/thirdparty/perfetto/protos/perfetto/config/profiling/perf_event_config_pb2.py +0 -43
  47. micromegas/thirdparty/perfetto/protos/perfetto/config/statsd/atom_ids_pb2.py +0 -36
  48. micromegas/thirdparty/perfetto/protos/perfetto/config/statsd/statsd_tracing_config_pb2.py +0 -39
  49. micromegas/thirdparty/perfetto/protos/perfetto/config/sys_stats/sys_stats_config_pb2.py +0 -39
  50. micromegas/thirdparty/perfetto/protos/perfetto/config/system_info/system_info_pb2.py +0 -36
  51. micromegas/thirdparty/perfetto/protos/perfetto/config/test_config_pb2.py +0 -38
  52. micromegas/thirdparty/perfetto/protos/perfetto/config/trace_config_pb2.py +0 -90
  53. micromegas/thirdparty/perfetto/protos/perfetto/config/track_event/track_event_config_pb2.py +0 -36
  54. micromegas/thirdparty/perfetto/protos/perfetto/trace/android/android_game_intervention_list_pb2.py +0 -40
  55. micromegas/thirdparty/perfetto/protos/perfetto/trace/android/android_log_pb2.py +0 -43
  56. micromegas/thirdparty/perfetto/protos/perfetto/trace/android/android_system_property_pb2.py +0 -38
  57. micromegas/thirdparty/perfetto/protos/perfetto/trace/android/camera_event_pb2.py +0 -48
  58. micromegas/thirdparty/perfetto/protos/perfetto/trace/android/frame_timeline_event_pb2.py +0 -54
  59. micromegas/thirdparty/perfetto/protos/perfetto/trace/android/gpu_mem_event_pb2.py +0 -36
  60. micromegas/thirdparty/perfetto/protos/perfetto/trace/android/graphics/rect_pb2.py +0 -36
  61. micromegas/thirdparty/perfetto/protos/perfetto/trace/android/graphics_frame_event_pb2.py +0 -40
  62. micromegas/thirdparty/perfetto/protos/perfetto/trace/android/initial_display_state_pb2.py +0 -36
  63. micromegas/thirdparty/perfetto/protos/perfetto/trace/android/network_trace_pb2.py +0 -46
  64. micromegas/thirdparty/perfetto/protos/perfetto/trace/android/packages_list_pb2.py +0 -38
  65. micromegas/thirdparty/perfetto/protos/perfetto/trace/android/pixel_modem_events_pb2.py +0 -38
  66. micromegas/thirdparty/perfetto/protos/perfetto/trace/android/protolog_pb2.py +0 -43
  67. micromegas/thirdparty/perfetto/protos/perfetto/trace/android/shell_transition_pb2.py +0 -42
  68. micromegas/thirdparty/perfetto/protos/perfetto/trace/android/surfaceflinger_common_pb2.py +0 -59
  69. micromegas/thirdparty/perfetto/protos/perfetto/trace/android/surfaceflinger_layers_pb2.py +0 -72
  70. micromegas/thirdparty/perfetto/protos/perfetto/trace/android/surfaceflinger_transactions_pb2.py +0 -76
  71. micromegas/thirdparty/perfetto/protos/perfetto/trace/android/winscope_extensions_pb2.py +0 -36
  72. micromegas/thirdparty/perfetto/protos/perfetto/trace/chrome/chrome_benchmark_metadata_pb2.py +0 -36
  73. micromegas/thirdparty/perfetto/protos/perfetto/trace/chrome/chrome_metadata_pb2.py +0 -50
  74. micromegas/thirdparty/perfetto/protos/perfetto/trace/chrome/chrome_trace_event_pb2.py +0 -56
  75. micromegas/thirdparty/perfetto/protos/perfetto/trace/chrome/chrome_trigger_pb2.py +0 -36
  76. micromegas/thirdparty/perfetto/protos/perfetto/trace/chrome/v8_pb2.py +0 -70
  77. micromegas/thirdparty/perfetto/protos/perfetto/trace/clock_snapshot_pb2.py +0 -41
  78. micromegas/thirdparty/perfetto/protos/perfetto/trace/etw/etw_event_bundle_pb2.py +0 -37
  79. micromegas/thirdparty/perfetto/protos/perfetto/trace/etw/etw_event_pb2.py +0 -37
  80. micromegas/thirdparty/perfetto/protos/perfetto/trace/etw/etw_pb2.py +0 -48
  81. micromegas/thirdparty/perfetto/protos/perfetto/trace/extension_descriptor_pb2.py +0 -37
  82. micromegas/thirdparty/perfetto/protos/perfetto/trace/filesystem/inode_file_map_pb2.py +0 -40
  83. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/android_fs_pb2.py +0 -46
  84. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/binder_pb2.py +0 -52
  85. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/block_pb2.py +0 -72
  86. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/cgroup_pb2.py +0 -52
  87. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/clk_pb2.py +0 -40
  88. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/cma_pb2.py +0 -38
  89. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/compaction_pb2.py +0 -62
  90. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/cpuhp_pb2.py +0 -44
  91. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/cros_ec_pb2.py +0 -36
  92. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/dcvsh_pb2.py +0 -36
  93. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/dma_fence_pb2.py +0 -44
  94. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/dmabuf_heap_pb2.py +0 -36
  95. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/dpu_pb2.py +0 -42
  96. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/drm_pb2.py +0 -38
  97. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/ext4_pb2.py +0 -224
  98. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/f2fs_pb2.py +0 -106
  99. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/fastrpc_pb2.py +0 -44
  100. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/fence_pb2.py +0 -42
  101. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/filemap_pb2.py +0 -38
  102. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/ftrace_event_bundle_pb2.py +0 -66
  103. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/ftrace_event_pb2.py +0 -105
  104. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/ftrace_pb2.py +0 -40
  105. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/ftrace_stats_pb2.py +0 -42
  106. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/g2d_pb2.py +0 -36
  107. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/generic_pb2.py +0 -38
  108. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/google_icc_trace_pb2.py +0 -36
  109. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/google_irm_trace_pb2.py +0 -36
  110. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/gpu_mem_pb2.py +0 -36
  111. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/gpu_scheduler_pb2.py +0 -40
  112. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/hyp_pb2.py +0 -44
  113. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/i2c_pb2.py +0 -50
  114. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/ion_pb2.py +0 -36
  115. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/ipi_pb2.py +0 -40
  116. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/irq_pb2.py +0 -44
  117. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/kgsl_pb2.py +0 -36
  118. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/kmem_pb2.py +0 -122
  119. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/kvm_pb2.py +0 -106
  120. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/lowmemorykiller_pb2.py +0 -36
  121. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/lwis_pb2.py +0 -36
  122. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/mali_pb2.py +0 -98
  123. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/mdss_pb2.py +0 -76
  124. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/mm_event_pb2.py +0 -36
  125. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/net_pb2.py +0 -42
  126. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/oom_pb2.py +0 -38
  127. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/panel_pb2.py +0 -42
  128. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/perf_trace_counters_pb2.py +0 -36
  129. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/power_pb2.py +0 -60
  130. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/printk_pb2.py +0 -36
  131. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/raw_syscalls_pb2.py +0 -38
  132. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/regulator_pb2.py +0 -48
  133. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/rpm_pb2.py +0 -36
  134. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/samsung_pb2.py +0 -36
  135. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/sched_pb2.py +0 -64
  136. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/scm_pb2.py +0 -38
  137. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/sde_pb2.py +0 -46
  138. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/signal_pb2.py +0 -38
  139. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/skb_pb2.py +0 -36
  140. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/sock_pb2.py +0 -36
  141. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/sync_pb2.py +0 -40
  142. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/synthetic_pb2.py +0 -38
  143. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/systrace_pb2.py +0 -36
  144. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/task_pb2.py +0 -38
  145. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/tcp_pb2.py +0 -36
  146. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/thermal_exynos_pb2.py +0 -38
  147. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/thermal_pb2.py +0 -38
  148. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/trusty_pb2.py +0 -70
  149. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/ufs_pb2.py +0 -38
  150. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/v4l2_pb2.py +0 -46
  151. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/virtio_gpu_pb2.py +0 -38
  152. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/virtio_video_pb2.py +0 -42
  153. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/vmscan_pb2.py +0 -46
  154. micromegas/thirdparty/perfetto/protos/perfetto/trace/ftrace/workqueue_pb2.py +0 -42
  155. micromegas/thirdparty/perfetto/protos/perfetto/trace/gpu/gpu_counter_event_pb2.py +0 -39
  156. micromegas/thirdparty/perfetto/protos/perfetto/trace/gpu/gpu_log_pb2.py +0 -38
  157. micromegas/thirdparty/perfetto/protos/perfetto/trace/gpu/gpu_render_stage_event_pb2.py +0 -58
  158. micromegas/thirdparty/perfetto/protos/perfetto/trace/gpu/vulkan_api_event_pb2.py +0 -40
  159. micromegas/thirdparty/perfetto/protos/perfetto/trace/gpu/vulkan_memory_event_pb2.py +0 -44
  160. micromegas/thirdparty/perfetto/protos/perfetto/trace/interned_data/interned_data_pb2.py +0 -45
  161. micromegas/thirdparty/perfetto/protos/perfetto/trace/memory_graph_pb2.py +0 -48
  162. micromegas/thirdparty/perfetto/protos/perfetto/trace/perfetto/perfetto_metatrace_pb2.py +0 -40
  163. micromegas/thirdparty/perfetto/protos/perfetto/trace/perfetto/tracing_service_event_pb2.py +0 -36
  164. micromegas/thirdparty/perfetto/protos/perfetto/trace/power/android_energy_estimation_breakdown_pb2.py +0 -39
  165. micromegas/thirdparty/perfetto/protos/perfetto/trace/power/android_entity_state_residency_pb2.py +0 -40
  166. micromegas/thirdparty/perfetto/protos/perfetto/trace/power/battery_counters_pb2.py +0 -36
  167. micromegas/thirdparty/perfetto/protos/perfetto/trace/power/power_rails_pb2.py +0 -40
  168. micromegas/thirdparty/perfetto/protos/perfetto/trace/profiling/deobfuscation_pb2.py +0 -40
  169. micromegas/thirdparty/perfetto/protos/perfetto/trace/profiling/heap_graph_pb2.py +0 -57
  170. micromegas/thirdparty/perfetto/protos/perfetto/trace/profiling/profile_common_pb2.py +0 -50
  171. micromegas/thirdparty/perfetto/protos/perfetto/trace/profiling/profile_packet_pb2.py +0 -72
  172. micromegas/thirdparty/perfetto/protos/perfetto/trace/profiling/smaps_pb2.py +0 -38
  173. micromegas/thirdparty/perfetto/protos/perfetto/trace/ps/process_stats_pb2.py +0 -42
  174. micromegas/thirdparty/perfetto/protos/perfetto/trace/ps/process_tree_pb2.py +0 -40
  175. micromegas/thirdparty/perfetto/protos/perfetto/trace/remote_clock_sync_pb2.py +0 -39
  176. micromegas/thirdparty/perfetto/protos/perfetto/trace/statsd/statsd_atom_pb2.py +0 -38
  177. micromegas/thirdparty/perfetto/protos/perfetto/trace/sys_stats/sys_stats_pb2.py +0 -55
  178. micromegas/thirdparty/perfetto/protos/perfetto/trace/system_info/cpu_info_pb2.py +0 -38
  179. micromegas/thirdparty/perfetto/protos/perfetto/trace/system_info_pb2.py +0 -38
  180. micromegas/thirdparty/perfetto/protos/perfetto/trace/test_event_pb2.py +0 -39
  181. micromegas/thirdparty/perfetto/protos/perfetto/trace/trace_packet_defaults_pb2.py +0 -39
  182. micromegas/thirdparty/perfetto/protos/perfetto/trace/trace_packet_pb2.py +0 -107
  183. micromegas/thirdparty/perfetto/protos/perfetto/trace/trace_pb2.py +0 -37
  184. micromegas/thirdparty/perfetto/protos/perfetto/trace/trace_uuid_pb2.py +0 -36
  185. micromegas/thirdparty/perfetto/protos/perfetto/trace/track_event/chrome_active_processes_pb2.py +0 -36
  186. micromegas/thirdparty/perfetto/protos/perfetto/trace/track_event/chrome_application_state_info_pb2.py +0 -38
  187. micromegas/thirdparty/perfetto/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state_pb2.py +0 -75
  188. micromegas/thirdparty/perfetto/protos/perfetto/trace/track_event/chrome_content_settings_event_info_pb2.py +0 -36
  189. micromegas/thirdparty/perfetto/protos/perfetto/trace/track_event/chrome_frame_reporter_pb2.py +0 -44
  190. micromegas/thirdparty/perfetto/protos/perfetto/trace/track_event/chrome_histogram_sample_pb2.py +0 -38
  191. micromegas/thirdparty/perfetto/protos/perfetto/trace/track_event/chrome_keyed_service_pb2.py +0 -36
  192. micromegas/thirdparty/perfetto/protos/perfetto/trace/track_event/chrome_latency_info_pb2.py +0 -42
  193. micromegas/thirdparty/perfetto/protos/perfetto/trace/track_event/chrome_legacy_ipc_pb2.py +0 -38
  194. micromegas/thirdparty/perfetto/protos/perfetto/trace/track_event/chrome_message_pump_pb2.py +0 -36
  195. micromegas/thirdparty/perfetto/protos/perfetto/trace/track_event/chrome_mojo_event_info_pb2.py +0 -36
  196. micromegas/thirdparty/perfetto/protos/perfetto/trace/track_event/chrome_process_descriptor_pb2.py +0 -38
  197. micromegas/thirdparty/perfetto/protos/perfetto/trace/track_event/chrome_renderer_scheduler_state_pb2.py +0 -38
  198. micromegas/thirdparty/perfetto/protos/perfetto/trace/track_event/chrome_thread_descriptor_pb2.py +0 -38
  199. micromegas/thirdparty/perfetto/protos/perfetto/trace/track_event/chrome_user_event_pb2.py +0 -36
  200. micromegas/thirdparty/perfetto/protos/perfetto/trace/track_event/chrome_window_handle_event_info_pb2.py +0 -36
  201. micromegas/thirdparty/perfetto/protos/perfetto/trace/track_event/counter_descriptor_pb2.py +0 -40
  202. micromegas/thirdparty/perfetto/protos/perfetto/trace/track_event/debug_annotation_pb2.py +0 -44
  203. micromegas/thirdparty/perfetto/protos/perfetto/trace/track_event/log_message_pb2.py +0 -40
  204. micromegas/thirdparty/perfetto/protos/perfetto/trace/track_event/pixel_modem_pb2.py +0 -36
  205. micromegas/thirdparty/perfetto/protos/perfetto/trace/track_event/process_descriptor_pb2.py +0 -38
  206. micromegas/thirdparty/perfetto/protos/perfetto/trace/track_event/range_of_interest_pb2.py +0 -36
  207. micromegas/thirdparty/perfetto/protos/perfetto/trace/track_event/screenshot_pb2.py +0 -36
  208. micromegas/thirdparty/perfetto/protos/perfetto/trace/track_event/source_location_pb2.py +0 -38
  209. micromegas/thirdparty/perfetto/protos/perfetto/trace/track_event/task_execution_pb2.py +0 -36
  210. micromegas/thirdparty/perfetto/protos/perfetto/trace/track_event/thread_descriptor_pb2.py +0 -38
  211. micromegas/thirdparty/perfetto/protos/perfetto/trace/track_event/track_descriptor_pb2.py +0 -41
  212. micromegas/thirdparty/perfetto/protos/perfetto/trace/track_event/track_event_pb2.py +0 -74
  213. micromegas/thirdparty/perfetto/protos/perfetto/trace/translation/translation_table_pb2.py +0 -70
  214. micromegas/thirdparty/perfetto/protos/perfetto/trace/trigger_pb2.py +0 -36
  215. micromegas/thirdparty/perfetto/protos/perfetto/trace/ui_state_pb2.py +0 -38
  216. micromegas-0.11.0.dist-info/METADATA +0 -251
  217. micromegas-0.11.0.dist-info/RECORD +0 -215
  218. {micromegas-0.11.0.dist-info → micromegas-0.13.0.dist-info}/WHEEL +0 -0
@@ -31,7 +31,7 @@ class MicromegasMiddlewareFactory(flight.ClientMiddlewareFactory):
31
31
  return MicromegasMiddleware(self.headers)
32
32
 
33
33
 
34
- def make_call_headers(begin, end):
34
+ def make_call_headers(begin, end, preserve_dictionary=False):
35
35
  call_headers = []
36
36
  if begin is not None:
37
37
  call_headers.append(
@@ -47,6 +47,13 @@ def make_call_headers(begin, end):
47
47
  time.format_datetime(end).encode("utf8"),
48
48
  )
49
49
  )
50
+ if preserve_dictionary:
51
+ call_headers.append(
52
+ (
53
+ "preserve_dictionary".encode("utf8"),
54
+ "true".encode("utf8"),
55
+ )
56
+ )
50
57
  return call_headers
51
58
 
52
59
 
@@ -81,15 +88,83 @@ def make_ingest_flight_desc(table_name):
81
88
  desc = make_arrow_flight_descriptor(ingest_statement)
82
89
  return desc
83
90
 
91
+
84
92
  class PreparedStatement:
85
- def __init__(self, prepared_statement_result ):
86
- self.query = prepared_statement_result.prepared_statement_handle.decode('utf8')
93
+ """Represents a prepared SQL statement with its result schema.
94
+
95
+ Prepared statements in Micromegas are primarily used for schema discovery -
96
+ determining the structure of query results without executing the query.
97
+ This is useful for query validation and building dynamic interfaces.
98
+
99
+ Attributes:
100
+ query (str): The SQL query string for this prepared statement.
101
+ dataset_schema (pyarrow.Schema): The schema (column names and types) of the result set.
102
+
103
+ Example:
104
+ >>> stmt = client.prepare_statement("SELECT time, level, msg FROM log_entries")
105
+ >>> print(stmt.query)
106
+ >>> # Output: "SELECT time, level, msg FROM log_entries"
107
+ >>>
108
+ >>> # Inspect the schema without running the query
109
+ >>> for field in stmt.dataset_schema:
110
+ ... print(f"{field.name}: {field.type}")
111
+ >>> # Output: time: timestamp[ns]
112
+ >>> # level: int32
113
+ >>> # msg: string
114
+ """
115
+
116
+ def __init__(self, prepared_statement_result):
117
+ """Initialize a PreparedStatement from server response.
118
+
119
+ Args:
120
+ prepared_statement_result: The server's response containing the prepared
121
+ statement handle and dataset schema.
122
+ """
123
+ self.query = prepared_statement_result.prepared_statement_handle.decode("utf8")
87
124
  reader = pyarrow.ipc.open_stream(prepared_statement_result.dataset_schema)
88
125
  self.dataset_schema = reader.schema
89
126
  reader.close()
90
127
 
128
+
91
129
  class FlightSQLClient:
92
- def __init__(self, uri, headers=None):
130
+ """Client for querying Micromegas observability data using Apache Arrow FlightSQL.
131
+
132
+ This client provides high-performance access to telemetry data stored in Micromegas,
133
+ supporting both simple queries and advanced features like prepared statements,
134
+ bulk ingestion, and partition management.
135
+
136
+ The client uses Apache Arrow's columnar format for efficient data transfer and
137
+ supports streaming for large result sets.
138
+ """
139
+
140
+ def __init__(self, uri, headers=None, preserve_dictionary=False):
141
+ """Initialize a FlightSQL client connection.
142
+
143
+ Args:
144
+ uri (str): The FlightSQL server URI (e.g., "grpc://localhost:50051").
145
+ Use "grpc://" for unencrypted connections or "grpc+tls://" for TLS.
146
+ headers (dict, optional): Custom headers for authentication or metadata.
147
+ Example: {"authorization": "Bearer token123"}
148
+ preserve_dictionary (bool, optional): When True, preserve dictionary encoding in
149
+ Arrow arrays for memory efficiency. Useful when using dictionary-encoded UDFs.
150
+ Defaults to False for backward compatibility.
151
+
152
+ Example:
153
+ >>> # Connect to local server
154
+ >>> client = FlightSQLClient("grpc://localhost:50051")
155
+ >>>
156
+ >>> # Connect with authentication
157
+ >>> client = FlightSQLClient(
158
+ ... "grpc+tls://remote-server:50051",
159
+ ... headers={"authorization": "Bearer mytoken"}
160
+ ... )
161
+ >>>
162
+ >>> # Connect with dictionary preservation for memory efficiency
163
+ >>> client = FlightSQLClient(
164
+ ... "grpc://localhost:50051",
165
+ ... preserve_dictionary=True
166
+ ... )
167
+ """
93
168
  fh = open(certifi.where(), "r")
94
169
  cert = fh.read()
95
170
  fh.close()
@@ -97,9 +172,115 @@ class FlightSQLClient:
97
172
  self.__flight_client = flight.connect(
98
173
  location=uri, tls_root_certs=cert, middleware=[factory]
99
174
  )
175
+ self.__preserve_dictionary = preserve_dictionary
176
+
177
+ def _prepare_table_for_pandas(self, table):
178
+ """Prepare Arrow table with dictionary columns for pandas conversion.
179
+
180
+ As of PyArrow/pandas 2024-2025, dictionary-encoded complex types
181
+ (List, Struct, Union) cannot be converted directly to pandas due to
182
+ "ArrowNotImplementedError: Unification of ... dictionaries is not implemented".
183
+
184
+ This method converts problematic dictionary columns back to regular arrays
185
+ while preserving memory efficiency during Arrow processing.
186
+ """
187
+ import pyarrow.compute as pc
188
+
189
+ columns = []
190
+ column_names = []
191
+
192
+ for i, column in enumerate(table.columns):
193
+ column_name = table.column_names[i]
194
+ column_names.append(column_name)
195
+
196
+ # Check if this is a dictionary-encoded column
197
+ if pyarrow.types.is_dictionary(column.type):
198
+ value_type = column.type.value_type
199
+
200
+ # Convert dictionary-encoded complex types that pandas can't handle
201
+ if (
202
+ pyarrow.types.is_list(value_type)
203
+ or pyarrow.types.is_struct(value_type)
204
+ or pyarrow.types.is_union(value_type)
205
+ ):
206
+ # Manually decode dictionary by reconstructing the array
207
+ # This works around PyArrow's casting limitations
208
+
209
+ # Decode each chunk of the dictionary column
210
+ reconstructed_chunks = []
211
+
212
+ if hasattr(column, "chunks"):
213
+ # ChunkedArray case
214
+ for chunk in column.chunks:
215
+ indices = chunk.indices
216
+ dictionary = chunk.dictionary
217
+ reconstructed_chunk = pc.take(dictionary, indices)
218
+ reconstructed_chunks.append(reconstructed_chunk)
219
+
220
+ # Create a new ChunkedArray from reconstructed chunks
221
+ reconstructed = pyarrow.chunked_array(reconstructed_chunks)
222
+ else:
223
+ # Single Array case
224
+ indices = column.indices
225
+ dictionary = column.dictionary
226
+ reconstructed = pc.take(dictionary, indices)
227
+
228
+ columns.append(reconstructed)
229
+ else:
230
+ # Keep simple dictionary types (strings, numbers) for pandas
231
+ # These work fine and provide memory benefits in pandas too
232
+ columns.append(column)
233
+ else:
234
+ # Non-dictionary columns are fine as-is
235
+ columns.append(column)
236
+
237
+ return pyarrow.Table.from_arrays(columns, names=column_names)
100
238
 
101
239
  def query(self, sql, begin=None, end=None):
102
- call_headers = make_call_headers(begin, end)
240
+ """Execute a SQL query and return results as a pandas DataFrame.
241
+
242
+ This method executes the provided SQL query and returns all results in memory
243
+ as a pandas DataFrame. For large result sets, consider using query_stream() instead.
244
+
245
+ Args:
246
+ sql (str): The SQL query to execute. Can use any supported SQL syntax including
247
+ JOINs, aggregations, window functions, etc.
248
+ begin (datetime or str, optional): Start time for partition pruning. Significantly
249
+ improves performance by eliminating irrelevant partitions before query execution.
250
+ Can be a timezone-aware datetime or RFC3339 string (e.g., "2024-01-01T00:00:00Z").
251
+ end (datetime or str, optional): End time for partition pruning. Should be used
252
+ together with begin for optimal performance.
253
+
254
+ Returns:
255
+ pandas.DataFrame: Query results with appropriate column types. When the client was
256
+ created with preserve_dictionary=True, dictionary-encoded columns will maintain
257
+ their encoding for memory efficiency.
258
+
259
+ Raises:
260
+ Exception: If the query fails due to syntax errors, missing tables, or server issues.
261
+
262
+ Example:
263
+ >>> import datetime
264
+ >>>
265
+ >>> # Query with time range for optimal performance
266
+ >>> end = datetime.datetime.now(datetime.timezone.utc)
267
+ >>> begin = end - datetime.timedelta(hours=1)
268
+ >>> df = client.query(
269
+ ... "SELECT time, level, msg FROM log_entries WHERE level <= 3",
270
+ ... begin, end
271
+ ... )
272
+ >>>
273
+ >>> # For dictionary preservation, create client with preserve_dictionary=True
274
+ >>> dict_client = FlightSQLClient("grpc://localhost:50051", preserve_dictionary=True)
275
+ >>> df = dict_client.query("SELECT dict_encoded_column FROM table")
276
+
277
+ Performance Note:
278
+ Always provide begin/end parameters when querying time-series data to enable
279
+ partition pruning, which can improve query performance by 10-100x.
280
+ Use preserve_dictionary=True in client constructor with dictionary-encoded UDFs
281
+ for significant memory reduction.
282
+ """
283
+ call_headers = make_call_headers(begin, end, self.__preserve_dictionary)
103
284
  options = flight.FlightCallOptions(headers=call_headers)
104
285
  ticket = make_query_ticket(sql)
105
286
  reader = self.__flight_client.do_get(ticket, options=options)
@@ -107,18 +288,133 @@ class FlightSQLClient:
107
288
  for chunk in reader:
108
289
  record_batches.append(chunk.data)
109
290
  table = pyarrow.Table.from_batches(record_batches, reader.schema)
291
+
292
+ # Handle dictionary-encoded columns that pandas can't convert directly
293
+ if self.__preserve_dictionary:
294
+ table = self._prepare_table_for_pandas(table)
295
+
110
296
  return table.to_pandas()
111
297
 
112
298
  def query_stream(self, sql, begin=None, end=None):
299
+ """Execute a SQL query and stream results as Arrow RecordBatch objects.
300
+
301
+ This method is ideal for large result sets as it processes data in chunks,
302
+ avoiding memory issues and allowing processing to start before the query completes.
303
+
304
+ Args:
305
+ sql (str): The SQL query to execute.
306
+ begin (datetime or str, optional): Start time for partition pruning.
307
+ Can be a timezone-aware datetime or RFC3339 string.
308
+ end (datetime or str, optional): End time for partition pruning.
309
+
310
+ Yields:
311
+ pyarrow.RecordBatch: Chunks of query results. Each batch contains a subset
312
+ of rows with all columns from the query. When the client was created with
313
+ preserve_dictionary=True, dictionary-encoded columns will maintain their encoding.
314
+
315
+ Example:
316
+ >>> # Stream and process large dataset
317
+ >>> total_errors = 0
318
+ >>> for batch in client.query_stream(
319
+ ... "SELECT * FROM log_entries WHERE level <= 2",
320
+ ... begin, end
321
+ ... ):
322
+ ... df_chunk = batch.to_pandas()
323
+ ... total_errors += len(df_chunk)
324
+ ... # Process chunk and release memory
325
+ ... print(f"Total errors: {total_errors}")
326
+ >>>
327
+ >>> # Stream with dictionary preservation
328
+ >>> dict_client = FlightSQLClient("grpc://localhost:50051", preserve_dictionary=True)
329
+ >>> for batch in dict_client.query_stream("SELECT dict_encoded_column FROM table"):
330
+ ... # Process dictionary-encoded data efficiently
331
+ ... pass
332
+
333
+ Performance Note:
334
+ Streaming is recommended when:
335
+ - Result set is larger than 100MB
336
+ - You want to start processing before the query completes
337
+ - Memory usage needs to be controlled
338
+ Use preserve_dictionary=True in client constructor with dictionary-encoded UDFs
339
+ for significant memory reduction.
340
+ """
113
341
  ticket = make_query_ticket(sql)
114
- call_headers = make_call_headers(begin, end)
342
+ call_headers = make_call_headers(begin, end, self.__preserve_dictionary)
115
343
  options = flight.FlightCallOptions(headers=call_headers)
116
344
  reader = self.__flight_client.do_get(ticket, options=options)
117
345
  record_batches = []
118
346
  for chunk in reader:
119
347
  yield chunk.data
120
348
 
349
+ def query_arrow(self, sql, begin=None, end=None):
350
+ """Execute a SQL query and return results as an Arrow Table.
351
+
352
+ This method preserves dictionary encoding and avoids pandas conversion issues.
353
+ Useful for working directly with Arrow data or when pandas can't handle
354
+ dictionary-encoded complex types.
355
+
356
+ Args:
357
+ sql (str): The SQL query to execute.
358
+ begin (datetime or str, optional): Start time for partition pruning.
359
+ end (datetime or str, optional): End time for partition pruning.
360
+
361
+ Returns:
362
+ pyarrow.Table: Query results as Arrow Table with preserved dictionary encoding.
363
+
364
+ Example:
365
+ >>> # Get Arrow table with preserved dictionary encoding
366
+ >>> table = client.query_arrow("SELECT dict_encoded_column FROM table")
367
+ >>> print(table.schema) # Shows dictionary<...> types
368
+ >>>
369
+ >>> # Work with Arrow directly to avoid pandas limitations
370
+ >>> for batch in table.to_batches():
371
+ ... # Process Arrow data without pandas conversion
372
+ ... pass
373
+ """
374
+ call_headers = make_call_headers(begin, end, self.__preserve_dictionary)
375
+ options = flight.FlightCallOptions(headers=call_headers)
376
+ ticket = make_query_ticket(sql)
377
+ reader = self.__flight_client.do_get(ticket, options=options)
378
+ record_batches = []
379
+ for chunk in reader:
380
+ record_batches.append(chunk.data)
381
+ return pyarrow.Table.from_batches(record_batches, reader.schema)
382
+
121
383
  def prepare_statement(self, sql):
384
+ """Create a prepared statement to retrieve query schema without executing it.
385
+
386
+ Prepared statements in Micromegas are primarily used to determine the schema
387
+ (column names and types) of a query result without actually executing the query
388
+ and retrieving data. This is useful for validating queries or building dynamic
389
+ interfaces that need to know the result structure in advance.
390
+
391
+ Args:
392
+ sql (str): The SQL query to prepare and analyze.
393
+
394
+ Returns:
395
+ PreparedStatement: An object containing the query and its result schema.
396
+
397
+ Example:
398
+ >>> # Get schema information without executing the query
399
+ >>> stmt = client.prepare_statement(
400
+ ... "SELECT time, level, msg FROM log_entries WHERE level <= 3"
401
+ ... )
402
+ >>>
403
+ >>> # Access the schema
404
+ >>> print(stmt.dataset_schema)
405
+ >>> # Output: time: timestamp[ns]
406
+ >>> # level: int32
407
+ >>> # msg: string
408
+ >>>
409
+ >>> # The query text is also available
410
+ >>> print(stmt.query)
411
+ >>> # Output: "SELECT time, level, msg FROM log_entries WHERE level <= 3"
412
+
413
+ Note:
414
+ The primary purpose is schema discovery. The prepared statement can be
415
+ executed via prepared_statement_stream(), but this offers no performance
416
+ benefit over regular query_stream() in the current implementation.
417
+ """
122
418
  action = make_prepared_statement_action(sql)
123
419
  results = self.__flight_client.do_action(action)
124
420
  for result in list(results):
@@ -129,10 +425,93 @@ class FlightSQLClient:
129
425
  return PreparedStatement(res)
130
426
 
131
427
  def prepared_statement_stream(self, statement):
428
+ """Execute a prepared statement and stream results.
429
+
430
+ Executes a previously prepared statement and returns results as a stream of
431
+ Arrow RecordBatch objects. This is functionally equivalent to calling
432
+ query_stream() with the statement's SQL query.
433
+
434
+ Args:
435
+ statement (PreparedStatement): The prepared statement to execute,
436
+ obtained from prepare_statement().
437
+
438
+ Yields:
439
+ pyarrow.RecordBatch: Chunks of query results.
440
+
441
+ Example:
442
+ >>> # Prepare statement (mainly for schema discovery)
443
+ >>> stmt = client.prepare_statement("SELECT time, level, msg FROM log_entries")
444
+ >>>
445
+ >>> # Check schema before execution
446
+ >>> print(f"Query will return {len(stmt.dataset_schema)} columns")
447
+ >>>
448
+ >>> # Execute the prepared statement
449
+ >>> for batch in client.prepared_statement_stream(stmt):
450
+ ... df = batch.to_pandas()
451
+ ... print(f"Received batch with {len(df)} rows")
452
+
453
+ Note:
454
+ This offers no performance advantage over query_stream(statement.query).
455
+ The main benefit of prepared statements is schema discovery via prepare_statement().
456
+ """
132
457
  # because we are not serializing the logical plan in the prepared statement, we can just execute the query normally
133
- return self.query_stream( statement.query )
458
+ return self.query_stream(statement.query)
134
459
 
135
460
  def bulk_ingest(self, table_name, df):
461
+ """Bulk ingest a pandas DataFrame into a Micromegas metadata table.
462
+
463
+ This method efficiently loads metadata or replication data into Micromegas
464
+ tables using Arrow's columnar format. Primarily used for ingesting:
465
+ - processes: Process metadata and information
466
+ - streams: Event stream metadata
467
+ - blocks: Data block metadata
468
+ - payloads: Raw binary telemetry payloads (for replication)
469
+
470
+ Args:
471
+ table_name (str): The name of the target table. Supported tables:
472
+ 'processes', 'streams', 'blocks', 'payloads'.
473
+ df (pandas.DataFrame): The DataFrame to ingest. Column names and types
474
+ must exactly match the target table schema.
475
+
476
+ Returns:
477
+ DoPutUpdateResult or None: Server response containing ingestion statistics
478
+ such as number of records ingested, or None if no response.
479
+
480
+ Raises:
481
+ Exception: If ingestion fails due to schema mismatch, unsupported table,
482
+ or invalid data.
483
+
484
+ Example:
485
+ >>> import pandas as pd
486
+ >>> from datetime import datetime, timezone
487
+ >>>
488
+ >>> # Example: Replicate process metadata
489
+ >>> processes_df = pd.DataFrame({
490
+ ... 'process_id': ['550e8400-e29b-41d4-a716-446655440000'],
491
+ ... 'exe': ['/usr/bin/myapp'],
492
+ ... 'username': ['user'],
493
+ ... 'realname': ['User Name'],
494
+ ... 'computer': ['hostname'],
495
+ ... 'distro': ['Ubuntu 22.04'],
496
+ ... 'cpu_brand': ['Intel Core i7'],
497
+ ... 'tsc_frequency': [2400000000],
498
+ ... 'start_time': [datetime.now(timezone.utc)],
499
+ ... 'start_ticks': [1234567890],
500
+ ... 'insert_time': [datetime.now(timezone.utc)],
501
+ ... 'parent_process_id': [''],
502
+ ... 'properties': [[]]
503
+ ... })
504
+ >>>
505
+ >>> # Bulk ingest process metadata
506
+ >>> result = client.bulk_ingest('processes', processes_df)
507
+ >>> if result:
508
+ ... print(f"Ingested {result.record_count} process records")
509
+
510
+ Note:
511
+ This method is primarily intended for metadata replication and
512
+ administrative tasks. For normal telemetry data ingestion, use
513
+ the telemetry ingestion service HTTP API instead.
514
+ """
136
515
  desc = make_ingest_flight_desc(table_name)
137
516
  table = pyarrow.Table.from_pandas(df)
138
517
  writer, reader = self.__flight_client.do_put(desc, table.schema)
@@ -148,6 +527,41 @@ class FlightSQLClient:
148
527
  return None
149
528
 
150
529
  def retire_partitions(self, view_set_name, view_instance_id, begin, end):
530
+ """Remove materialized view partitions for a specific time range.
531
+
532
+ This method removes previously materialized partitions, which is useful for:
533
+ - Freeing up storage space
534
+ - Removing outdated materialized data
535
+ - Preparing for re-materialization with different settings
536
+
537
+ Args:
538
+ view_set_name (str): The name of the view set containing the partitions.
539
+ view_instance_id (str): The specific view instance identifier (usually a process_id).
540
+ begin (datetime): Start time of partitions to retire (inclusive).
541
+ end (datetime): End time of partitions to retire (exclusive).
542
+
543
+ Returns:
544
+ None: Prints status messages as partitions are retired.
545
+
546
+ Example:
547
+ >>> from datetime import datetime, timedelta, timezone
548
+ >>>
549
+ >>> # Retire partitions for the last 7 days
550
+ >>> end = datetime.now(timezone.utc)
551
+ >>> begin = end - timedelta(days=7)
552
+ >>>
553
+ >>> client.retire_partitions(
554
+ ... 'log_entries',
555
+ ... 'process-123-456',
556
+ ... begin,
557
+ ... end
558
+ ... )
559
+ # Output: Timestamps and status messages for each retired partition
560
+
561
+ Note:
562
+ This operation cannot be undone. Retired partitions must be re-materialized
563
+ if the data is needed again.
564
+ """
151
565
  sql = """
152
566
  SELECT time, msg
153
567
  FROM retire_partitions('{view_set_name}', '{view_instance_id}', '{begin}', '{end}')
@@ -164,6 +578,42 @@ class FlightSQLClient:
164
578
  def materialize_partitions(
165
579
  self, view_set_name, begin, end, partition_delta_seconds
166
580
  ):
581
+ """Create materialized view partitions for faster query performance.
582
+
583
+ Materialized partitions pre-compute and store query results in optimized format,
584
+ significantly improving query performance for frequently accessed data.
585
+
586
+ Args:
587
+ view_set_name (str): The name of the view set to materialize.
588
+ begin (datetime): Start time for materialization (inclusive).
589
+ end (datetime): End time for materialization (exclusive).
590
+ partition_delta_seconds (int): Size of each partition in seconds.
591
+ Common values: 3600 (hourly), 86400 (daily).
592
+
593
+ Returns:
594
+ None: Prints status messages as partitions are created.
595
+
596
+ Example:
597
+ >>> from datetime import datetime, timedelta, timezone
598
+ >>>
599
+ >>> # Materialize hourly partitions for the last 24 hours
600
+ >>> end = datetime.now(timezone.utc)
601
+ >>> begin = end - timedelta(days=1)
602
+ >>>
603
+ >>> client.materialize_partitions(
604
+ ... 'log_entries',
605
+ ... begin,
606
+ ... end,
607
+ ... 3600 # 1-hour partitions
608
+ ... )
609
+ # Output: Progress messages for each materialized partition
610
+
611
+ Performance Note:
612
+ Materialized partitions can improve query performance by 10-100x but
613
+ require additional storage. Choose partition size based on query patterns:
614
+ - Hourly (3600): For high-frequency queries on recent data
615
+ - Daily (86400): For historical analysis and reporting
616
+ """
167
617
  sql = """
168
618
  SELECT time, msg
169
619
  FROM materialize_partitions('{view_set_name}', '{begin}', '{end}', {partition_delta_seconds})
@@ -178,6 +628,38 @@ class FlightSQLClient:
178
628
  print(row["time"], row["msg"])
179
629
 
180
630
  def find_process(self, process_id):
631
+ """Find and retrieve metadata for a specific process.
632
+
633
+ Queries the processes table to get detailed information about a process
634
+ including its executable path, command line arguments, start time, and metadata.
635
+
636
+ Args:
637
+ process_id (str): The unique identifier of the process to find.
638
+ This is typically a UUID string.
639
+
640
+ Returns:
641
+ pandas.DataFrame: A DataFrame containing process information with columns:
642
+ - process_id: Unique process identifier
643
+ - exe: Executable path
644
+ - username: User who started the process
645
+ - realname: Real name of the user
646
+ - computer: Hostname where process is running
647
+ - start_time: When the process started
648
+ - parent_process_id: Parent process identifier
649
+ - metadata: Additional process metadata as JSON
650
+
651
+ Example:
652
+ >>> # Find a specific process
653
+ >>> process_info = client.find_process('550e8400-e29b-41d4-a716-446655440000')
654
+ >>> if not process_info.empty:
655
+ ... print(f"Process: {process_info['exe'].iloc[0]}")
656
+ ... print(f"Started: {process_info['start_time'].iloc[0]}")
657
+ ... else:
658
+ ... print("Process not found")
659
+
660
+ Note:
661
+ Returns an empty DataFrame if the process is not found.
662
+ """
181
663
  sql = """
182
664
  SELECT *
183
665
  FROM processes
@@ -188,6 +670,50 @@ class FlightSQLClient:
188
670
  return self.query(sql)
189
671
 
190
672
  def query_streams(self, begin, end, limit, process_id=None, tag_filter=None):
673
+ """Query event streams with optional filtering.
674
+
675
+ Retrieves information about event streams (collections of telemetry data)
676
+ within a time range, with optional filtering by process or tags.
677
+
678
+ Args:
679
+ begin (datetime): Start time for the query (inclusive).
680
+ end (datetime): End time for the query (exclusive).
681
+ limit (int): Maximum number of streams to return.
682
+ process_id (str, optional): Filter streams to a specific process.
683
+ tag_filter (str, optional): Filter streams that contain a specific tag.
684
+ Valid stream tags: 'log', 'metrics', 'cpu'.
685
+
686
+ Returns:
687
+ pandas.DataFrame: DataFrame containing stream information with columns:
688
+ - stream_id: Unique stream identifier
689
+ - process_id: Process that created the stream
690
+ - stream_type: Type of stream (e.g., 'LOG', 'METRIC', 'SPAN')
691
+ - tags: Array of tags associated with the stream
692
+ - properties: Additional stream properties
693
+ - time: Stream creation time
694
+
695
+ Example:
696
+ >>> from datetime import datetime, timedelta, timezone
697
+ >>>
698
+ >>> # Query all streams from the last hour
699
+ >>> end = datetime.now(timezone.utc)
700
+ >>> begin = end - timedelta(hours=1)
701
+ >>> streams = client.query_streams(begin, end, limit=100)
702
+ >>>
703
+ >>> # Query streams for a specific process
704
+ >>> streams = client.query_streams(
705
+ ... begin, end,
706
+ ... limit=50,
707
+ ... process_id='550e8400-e29b-41d4-a716-446655440000'
708
+ ... )
709
+ >>>
710
+ >>> # Query streams with a specific tag
711
+ >>> log_streams = client.query_streams(
712
+ ... begin, end,
713
+ ... limit=20,
714
+ ... tag_filter='log'
715
+ ... )
716
+ """
191
717
  conditions = []
192
718
  if process_id is not None:
193
719
  conditions.append("process_id='{process_id}'".format(process_id=process_id))
@@ -209,6 +735,42 @@ class FlightSQLClient:
209
735
  return self.query(sql, begin, end)
210
736
 
211
737
  def query_blocks(self, begin, end, limit, stream_id):
738
+ """Query data blocks within a specific stream.
739
+
740
+ Retrieves detailed information about data blocks (chunks of events) within
741
+ a stream. Blocks are the fundamental storage unit for telemetry data.
742
+
743
+ Args:
744
+ begin (datetime): Start time for the query (inclusive).
745
+ end (datetime): End time for the query (exclusive).
746
+ limit (int): Maximum number of blocks to return.
747
+ stream_id (str): The unique identifier of the stream to query.
748
+
749
+ Returns:
750
+ pandas.DataFrame: DataFrame containing block information with columns:
751
+ - block_id: Unique block identifier
752
+ - stream_id: Parent stream identifier
753
+ - begin_time: Earliest event time in the block
754
+ - end_time: Latest event time in the block
755
+ - nb_events: Number of events in the block
756
+ - payload_size: Size of the block in bytes
757
+ - metadata: Additional block metadata
758
+
759
+ Example:
760
+ >>> # First, find a stream
761
+ >>> streams = client.query_streams(begin, end, limit=1)
762
+ >>> if not streams.empty:
763
+ ... stream_id = streams['stream_id'].iloc[0]
764
+ ...
765
+ ... # Query blocks in that stream
766
+ ... blocks = client.query_blocks(begin, end, 100, stream_id)
767
+ ... print(f"Found {len(blocks)} blocks")
768
+ ... print(f"Total events: {blocks['nb_events'].sum()}")
769
+
770
+ Note:
771
+ Blocks are typically used for low-level data inspection and debugging.
772
+ For normal queries, use higher-level methods like query() or query_stream().
773
+ """
212
774
  sql = """
213
775
  SELECT *
214
776
  FROM blocks
@@ -220,6 +782,46 @@ class FlightSQLClient:
220
782
  return self.query(sql, begin, end)
221
783
 
222
784
  def query_spans(self, begin, end, limit, stream_id):
785
+ """Query thread spans (execution traces) for a specific stream.
786
+
787
+ Retrieves detailed span information showing the execution flow and timing
788
+ of operations within a stream. Spans are hierarchical and represent
789
+ function calls, operations, or logical units of work.
790
+
791
+ Args:
792
+ begin (datetime): Start time for the query (inclusive).
793
+ end (datetime): End time for the query (exclusive).
794
+ limit (int): Maximum number of spans to return.
795
+ stream_id (str): The stream identifier to query spans from.
796
+
797
+ Returns:
798
+ pandas.DataFrame: DataFrame containing span information with columns:
799
+ - span_id: Unique span identifier
800
+ - parent_span_id: Parent span for hierarchical traces
801
+ - name: Name of the operation or function
802
+ - begin_time: When the span started
803
+ - end_time: When the span completed
804
+ - duration: Duration in nanoseconds
805
+ - thread_id: Thread that executed the span
806
+ - properties: Additional span attributes
807
+
808
+ Example:
809
+ >>> # Query spans to analyze performance
810
+ >>> spans = client.query_spans(begin, end, 1000, stream_id)
811
+ >>>
812
+ >>> # Find slowest operations
813
+ >>> slow_spans = spans.nlargest(10, 'duration')
814
+ >>> for _, span in slow_spans.iterrows():
815
+ ... print(f"{span['name']}: {span['duration']/1000000:.2f}ms")
816
+ >>>
817
+ >>> # Analyze span hierarchy
818
+ >>> root_spans = spans[spans['parent_span_id'].isna()]
819
+ >>> print(f"Found {len(root_spans)} root spans")
820
+
821
+ Note:
822
+ Spans are essential for performance analysis and distributed tracing.
823
+ Use with Perfetto trace generation for visualization.
824
+ """
223
825
  sql = """
224
826
  SELECT *
225
827
  FROM view_instance('thread_spans', '{stream_id}')