testlint_sdk/profiler/
mod.rs

1#![allow(dead_code)]
2
3pub mod common_format;
4pub mod cpp;
5pub mod csharp;
6pub mod go;
7pub mod java;
8pub mod php;
9pub mod python;
10pub mod ruby;
11pub mod rust;
12pub mod typescript;
13
14pub use crate::common::Language;
15pub use common_format::*;
16use std::fmt;
17use std::io;
18
19// Removed LanguageProfiler trait - only runtime profiling is supported
20
21#[derive(Debug)]
22pub struct ProfileResult {
23    pub language: String,
24    pub details: Vec<String>,
25}
26
27impl fmt::Display for ProfileResult {
28    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
29        writeln!(f, "=== Runtime Profiling Results for {} ===", self.language)?;
30
31        for detail in &self.details {
32            writeln!(f, "{}", detail)?;
33        }
34
35        Ok(())
36    }
37}
38
39pub struct Profiler {
40    language: Language,
41}
42
43impl Profiler {
44    pub fn new(language: Language) -> Self {
45        Profiler { language }
46    }
47
48    // Continuous runtime profiling - runs until interrupted
49    pub fn profile_continuous(&self, file_path: &str) -> Result<ProfileResult, io::Error> {
50        match self.language {
51            Language::Python => {
52                let profiler = python::PythonProfiler::new();
53                profiler
54                    .profile_continuous(file_path)
55                    .map_err(io::Error::other)
56            }
57            Language::Go => {
58                let profiler = go::GoProfiler::new();
59                profiler
60                    .profile_continuous(file_path)
61                    .map_err(io::Error::other)
62            }
63            Language::JavaScript | Language::TypeScript => {
64                let profiler = typescript::TypeScriptProfiler::new();
65                profiler
66                    .profile_continuous(file_path)
67                    .map_err(io::Error::other)
68            }
69            Language::Java => {
70                let profiler = java::JavaProfiler::new();
71                profiler
72                    .profile_continuous(file_path)
73                    .map_err(io::Error::other)
74            }
75            Language::Rust => {
76                let profiler = rust::RustProfiler::new();
77                profiler
78                    .profile_continuous(file_path)
79                    .map_err(io::Error::other)
80            }
81            Language::CSharp => {
82                let profiler = csharp::CSharpProfiler::new();
83                profiler
84                    .profile_continuous(file_path)
85                    .map_err(io::Error::other)
86            }
87            Language::Ruby => {
88                let profiler = ruby::RubyProfiler::new();
89                profiler
90                    .profile_continuous(file_path)
91                    .map_err(io::Error::other)
92            }
93            Language::Php => {
94                let profiler = php::PhpProfiler::new();
95                profiler
96                    .profile_continuous(file_path)
97                    .map_err(io::Error::other)
98            }
99            Language::Cpp => {
100                let profiler = cpp::CppProfiler::new();
101                profiler
102                    .profile_continuous(file_path)
103                    .map_err(io::Error::other)
104            }
105        }
106    }
107
108    // Attach to an existing process by PID
109    pub fn profile_pid(&self, pid: u32) -> Result<ProfileResult, io::Error> {
110        match self.language {
111            Language::Python => {
112                let profiler = python::PythonProfiler::new();
113                profiler.profile_pid(pid).map_err(io::Error::other)
114            }
115            Language::Go => Err(io::Error::new(
116                io::ErrorKind::Unsupported,
117                "Go profiler does not support PID attach. Use file profiling instead.",
118            )),
119            Language::JavaScript | Language::TypeScript => {
120                let profiler = typescript::TypeScriptProfiler::new();
121                profiler.profile_pid(pid).map_err(io::Error::other)
122            }
123            Language::Java => {
124                let profiler = java::JavaProfiler::new();
125                profiler.profile_pid(pid).map_err(io::Error::other)
126            }
127            Language::Rust => {
128                let profiler = rust::RustProfiler::new();
129                profiler.profile_pid(pid).map_err(io::Error::other)
130            }
131            Language::CSharp => {
132                let profiler = csharp::CSharpProfiler::new();
133                profiler.profile_pid(pid).map_err(io::Error::other)
134            }
135            Language::Ruby => {
136                let profiler = ruby::RubyProfiler::new();
137                profiler.profile_pid(pid).map_err(io::Error::other)
138            }
139            Language::Php => {
140                let profiler = php::PhpProfiler::new();
141                profiler.profile_pid(pid).map_err(io::Error::other)
142            }
143            Language::Cpp => {
144                let profiler = cpp::CppProfiler::new();
145                profiler.profile_pid(pid).map_err(io::Error::other)
146            }
147        }
148    }
149
150    pub fn profile_to_common_format(
151        &self,
152        file_path: &str,
153    ) -> Result<CommonProfileData, io::Error> {
154        match self.language {
155            Language::Python => {
156                let profiler = python::PythonProfiler::new();
157                profiler
158                    .profile_to_common_format(file_path)
159                    .map_err(io::Error::other)
160            }
161            Language::Go => {
162                let profiler = go::GoProfiler::new();
163                profiler
164                    .profile_to_common_format(file_path)
165                    .map_err(io::Error::other)
166            }
167            Language::JavaScript | Language::TypeScript => {
168                let profiler = typescript::TypeScriptProfiler::new();
169                profiler
170                    .profile_to_common_format(file_path)
171                    .map_err(io::Error::other)
172            }
173            Language::Java => {
174                let profiler = java::JavaProfiler::new();
175                profiler
176                    .profile_to_common_format(file_path)
177                    .map_err(io::Error::other)
178            }
179            // New languages generate specialized output formats that are more useful than JSON
180            Language::Rust | Language::CSharp | Language::Ruby | Language::Php | Language::Cpp => {
181                Err(io::Error::new(
182                    io::ErrorKind::Unsupported,
183                    format!(
184                        "{} generates specialized profiling output:\n\
185                         - Rust: flamegraph.svg (interactive visualization)\n\
186                         - C#: .nettrace (view with PerfView/speedscope)\n\
187                         - Ruby: flamegraph.svg via rbspy\n\
188                         - PHP: cachegrind files (view with KCacheGrind)\n\
189                         - C++: perf.data or callgrind files\n\
190                         These formats provide richer profiling data than generic JSON.",
191                        self.language
192                    ),
193                ))
194            }
195        }
196    }
197}