testlint_sdk/profiler/
mod.rs1#![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#[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 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 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 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}