Skip to main content

dbg_cli/session_db/
mod.rs

1//! SessionDb — SQLite-backed session store shared by the debug and
2//! profile tracks.
3//!
4//! Policy highlights (see `plans/sorted-nibbling-lovelace.md`):
5//!
6//! * **No backward compatibility.** Old DBs fail to load with a
7//!   re-collect message; see `schema::SCHEMA_VERSION`.
8//! * **Adaptation layer.** Raw native captures live under
9//!   `.dbg/sessions/<label>/raw/` and `layers.file` points at them —
10//!   SessionDb tables index, they do not replace.
11//! * **Two tracks, one DB.** Debug and profile commands write into
12//!   the same DB and join on canonical `(lang, fqn)` symbols.
13
14pub mod canonicalizer;
15pub mod collectors;
16pub mod lifecycle;
17pub mod schema;
18
19pub use canonicalizer::{CanonicalSymbol, Canonicalizer, for_lang};
20pub use collectors::{
21    CollectCtx, CollectTrigger, DisasmOutput, LiveDebugger, OnDemandCollector, persist_disasm,
22};
23
24use std::fmt;
25use std::str::FromStr;
26
27pub use lifecycle::{
28    CreateOptions, PrunePolicy, SessionDb, auto_label, compute_target_hash, group_key, prune,
29    raw_dir, sessions_dir,
30};
31pub use schema::SCHEMA_VERSION;
32
33/// The target classification that drives which domain tables exist
34/// and which profile collectors apply.
35#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
36pub enum TargetClass {
37    /// CUDA / PyTorch / Triton — driven by `gdbg`.
38    Gpu,
39    /// Native compiled binaries: C, C++, Rust, Zig, D, Nim, Go.
40    NativeCpu,
41    /// .NET / CoreCLR / Mono — C#, F#, VB.
42    ManagedDotnet,
43    /// HotSpot / GraalVM — Java, Kotlin, Scala.
44    Jvm,
45    /// CPython / PyPy.
46    Python,
47    /// Node.js / V8 — JavaScript, TypeScript.
48    JsNode,
49    /// MRI / YJIT — Ruby.
50    Ruby,
51    /// Zend — PHP.
52    Php,
53}
54
55impl TargetClass {
56    pub fn as_str(self) -> &'static str {
57        match self {
58            TargetClass::Gpu => "gpu",
59            TargetClass::NativeCpu => "native-cpu",
60            TargetClass::ManagedDotnet => "managed-dotnet",
61            TargetClass::Jvm => "jvm",
62            TargetClass::Python => "python",
63            TargetClass::JsNode => "node",
64            TargetClass::Ruby => "ruby",
65            TargetClass::Php => "php",
66        }
67    }
68}
69
70impl fmt::Display for TargetClass {
71    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72        f.write_str(self.as_str())
73    }
74}
75
76impl FromStr for TargetClass {
77    type Err = anyhow::Error;
78    fn from_str(s: &str) -> Result<Self, Self::Err> {
79        Ok(match s {
80            "gpu" => TargetClass::Gpu,
81            "native-cpu" => TargetClass::NativeCpu,
82            "managed-dotnet" => TargetClass::ManagedDotnet,
83            "jvm" => TargetClass::Jvm,
84            "python" => TargetClass::Python,
85            // Accept both the legacy "js-node" tag and the current "node" one.
86            "js-node" | "node" => TargetClass::JsNode,
87            "ruby" => TargetClass::Ruby,
88            "php" => TargetClass::Php,
89            other => anyhow::bail!("unknown target class: {other}"),
90        })
91    }
92}
93
94/// The session kind — debug sessions drive an interactive debugger,
95/// profile sessions collect and analyze samples.
96#[derive(Clone, Copy, Debug, PartialEq, Eq)]
97pub enum SessionKind {
98    Debug,
99    Profile,
100}
101
102impl SessionKind {
103    pub fn as_str(self) -> &'static str {
104        match self {
105            SessionKind::Debug => "debug",
106            SessionKind::Profile => "profile",
107        }
108    }
109}