pyroscope 0.3.0-x86_64-linux
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.
- checksums.yaml +7 -0
- data/LICENSE +202 -0
- data/README.md +57 -0
- data/elflib/rbspy/manylinux.sh +23 -0
- data/elflib/rbspy/pyproject.toml +7 -0
- data/elflib/rbspy/rbspy/__init__.py +0 -0
- data/elflib/rbspy/setup.cfg +22 -0
- data/elflib/rbspy/setup.py +46 -0
- data/elflib/thread_id/manylinux.sh +23 -0
- data/elflib/thread_id/pyproject.toml +7 -0
- data/elflib/thread_id/setup.cfg +22 -0
- data/elflib/thread_id/setup.py +46 -0
- data/elflib/thread_id/thread_id/__init__.py +0 -0
- data/ext/rbspy/Cargo.toml +27 -0
- data/ext/rbspy/Rakefile +164 -0
- data/ext/rbspy/build.rs +12 -0
- data/ext/rbspy/cbindgen.toml +22 -0
- data/ext/rbspy/extconf.rb +11 -0
- data/ext/rbspy/src/lib.rs +168 -0
- data/ext/thread_id/Cargo.toml +20 -0
- data/ext/thread_id/Rakefile +163 -0
- data/ext/thread_id/build.rs +12 -0
- data/ext/thread_id/cbindgen.toml +22 -0
- data/ext/thread_id/extconf.rb +11 -0
- data/ext/thread_id/src/lib.rs +4 -0
- data/lib/pyroscope/version.rb +3 -0
- data/lib/pyroscope.rb +101 -0
- data/lib/rbspy/rbspy.so +0 -0
- data/lib/rbspy.libs/libcom_err-f79b9776.so.2.1 +0 -0
- data/lib/rbspy.libs/libcrypto-142cf8a3.so.1.0.1e +0 -0
- data/lib/rbspy.libs/libgssapi_krb5-bb73e344.so.2.2 +0 -0
- data/lib/rbspy.libs/libk5crypto-ab4ddf4c.so.3.1 +0 -0
- data/lib/rbspy.libs/libkeyutils-68db41cc.so.1.3 +0 -0
- data/lib/rbspy.libs/libkrb5-7e4170ab.so.3.3 +0 -0
- data/lib/rbspy.libs/libkrb5support-2ce1fd50.so.0.1 +0 -0
- data/lib/rbspy.libs/libselinux-d72a37e2.so.1 +0 -0
- data/lib/rbspy.libs/libssl-09014658.so.1.0.1e +0 -0
- data/lib/thread_id/thread_id.so +0 -0
- data/pyroscope.gemspec +32 -0
- data/scripts/docker.sh +16 -0
- metadata +124 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
# The language to output bindings in
|
2
|
+
language = "C"
|
3
|
+
documentation_style = "C"
|
4
|
+
|
5
|
+
style = "type"
|
6
|
+
|
7
|
+
# An optional name to use as an include guard
|
8
|
+
include_guard = "RBSPY_H_"
|
9
|
+
# include a comment with the version of cbindgen used to generate the file
|
10
|
+
include_version = true
|
11
|
+
|
12
|
+
# An optional string of text to output at the beginning of the generated file
|
13
|
+
header = "/* Licensed under Apache-2.0 */"
|
14
|
+
autogen_warning = "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */"
|
15
|
+
|
16
|
+
braces = "SameLine"
|
17
|
+
tab_width = 2
|
18
|
+
line_length = 80
|
19
|
+
|
20
|
+
[parse]
|
21
|
+
# Do not parse dependent crates
|
22
|
+
parse_deps = false
|
@@ -0,0 +1,168 @@
|
|
1
|
+
use pyroscope::backend::Tag;
|
2
|
+
use pyroscope::PyroscopeAgent;
|
3
|
+
use pyroscope_rbspy::{rbspy_backend, RbspyConfig};
|
4
|
+
use std::ffi::CStr;
|
5
|
+
use std::mem::MaybeUninit;
|
6
|
+
use std::os::raw::c_char;
|
7
|
+
use std::sync::mpsc::{sync_channel, Receiver, SyncSender};
|
8
|
+
use std::sync::{Mutex, Once};
|
9
|
+
|
10
|
+
pub enum Signal {
|
11
|
+
Kill,
|
12
|
+
AddTag(u64, String, String),
|
13
|
+
RemoveTag(u64, String, String),
|
14
|
+
}
|
15
|
+
|
16
|
+
pub struct SignalPass {
|
17
|
+
inner_sender: Mutex<SyncSender<Signal>>,
|
18
|
+
inner_receiver: Mutex<Receiver<Signal>>,
|
19
|
+
}
|
20
|
+
|
21
|
+
fn signalpass() -> &'static SignalPass {
|
22
|
+
static mut SIGNAL_PASS: MaybeUninit<SignalPass> = MaybeUninit::uninit();
|
23
|
+
static ONCE: Once = Once::new();
|
24
|
+
|
25
|
+
ONCE.call_once(|| unsafe {
|
26
|
+
let (sender, receiver) = sync_channel(1);
|
27
|
+
let singleton = SignalPass {
|
28
|
+
inner_sender: Mutex::new(sender),
|
29
|
+
inner_receiver: Mutex::new(receiver),
|
30
|
+
};
|
31
|
+
SIGNAL_PASS = MaybeUninit::new(singleton);
|
32
|
+
});
|
33
|
+
|
34
|
+
unsafe { SIGNAL_PASS.assume_init_ref() }
|
35
|
+
}
|
36
|
+
|
37
|
+
#[no_mangle]
|
38
|
+
pub extern "C" fn initialize_agent(
|
39
|
+
application_name: *const c_char, server_address: *const c_char, auth_token: *const c_char,
|
40
|
+
sample_rate: u32, detect_subprocesses: bool, on_cpu: bool, report_pid: bool,
|
41
|
+
report_thread_id: bool, tags: *const c_char,
|
42
|
+
) -> bool {
|
43
|
+
let application_name = unsafe { CStr::from_ptr(application_name) }
|
44
|
+
.to_str()
|
45
|
+
.unwrap()
|
46
|
+
.to_string();
|
47
|
+
|
48
|
+
let server_address = unsafe { CStr::from_ptr(server_address) }
|
49
|
+
.to_str()
|
50
|
+
.unwrap()
|
51
|
+
.to_string();
|
52
|
+
|
53
|
+
let auth_token = unsafe { CStr::from_ptr(auth_token) }
|
54
|
+
.to_str()
|
55
|
+
.unwrap()
|
56
|
+
.to_string();
|
57
|
+
|
58
|
+
let tags_string = unsafe { CStr::from_ptr(tags) }
|
59
|
+
.to_str()
|
60
|
+
.unwrap()
|
61
|
+
.to_string();
|
62
|
+
|
63
|
+
let pid = std::process::id();
|
64
|
+
|
65
|
+
let s = signalpass();
|
66
|
+
|
67
|
+
std::thread::spawn(move || {
|
68
|
+
let rbspy_config = RbspyConfig::new(pid.try_into().unwrap())
|
69
|
+
.sample_rate(sample_rate)
|
70
|
+
.lock_process(false)
|
71
|
+
.with_subprocesses(detect_subprocesses)
|
72
|
+
.on_cpu(on_cpu)
|
73
|
+
.report_pid(report_pid)
|
74
|
+
.report_thread_id(report_thread_id);
|
75
|
+
|
76
|
+
let tags_ref = tags_string.as_str();
|
77
|
+
let tags = string_to_tags(tags_ref);
|
78
|
+
let rbspy = rbspy_backend(rbspy_config);
|
79
|
+
|
80
|
+
let mut agent_builder = PyroscopeAgent::builder(server_address, application_name)
|
81
|
+
.backend(rbspy)
|
82
|
+
.tags(tags);
|
83
|
+
|
84
|
+
if auth_token != "" {
|
85
|
+
agent_builder = agent_builder.auth_token(auth_token);
|
86
|
+
}
|
87
|
+
|
88
|
+
let agent = agent_builder.build().unwrap();
|
89
|
+
|
90
|
+
let agent_running = agent.start().unwrap();
|
91
|
+
|
92
|
+
while let Ok(signal) = s.inner_receiver.lock().unwrap().recv() {
|
93
|
+
match signal {
|
94
|
+
Signal::Kill => {
|
95
|
+
agent_running.stop().unwrap();
|
96
|
+
break;
|
97
|
+
}
|
98
|
+
Signal::AddTag(thread_id, key, value) => {
|
99
|
+
let tag = Tag::new(key, value);
|
100
|
+
agent_running.add_thread_tag(thread_id, tag).unwrap();
|
101
|
+
}
|
102
|
+
Signal::RemoveTag(thread_id, key, value) => {
|
103
|
+
let tag = Tag::new(key, value);
|
104
|
+
agent_running.remove_thread_tag(thread_id, tag).unwrap();
|
105
|
+
}
|
106
|
+
}
|
107
|
+
}
|
108
|
+
});
|
109
|
+
|
110
|
+
true
|
111
|
+
}
|
112
|
+
|
113
|
+
#[no_mangle]
|
114
|
+
pub extern "C" fn drop_agent() -> bool {
|
115
|
+
let s = signalpass();
|
116
|
+
s.inner_sender.lock().unwrap().send(Signal::Kill).unwrap();
|
117
|
+
true
|
118
|
+
}
|
119
|
+
|
120
|
+
#[no_mangle]
|
121
|
+
pub extern "C" fn add_tag(thread_id: u64, key: *const c_char, value: *const c_char) -> bool {
|
122
|
+
let s = signalpass();
|
123
|
+
let key = unsafe { CStr::from_ptr(key) }.to_str().unwrap().to_owned();
|
124
|
+
let value = unsafe { CStr::from_ptr(value) }
|
125
|
+
.to_str()
|
126
|
+
.unwrap()
|
127
|
+
.to_owned();
|
128
|
+
s.inner_sender
|
129
|
+
.lock()
|
130
|
+
.unwrap()
|
131
|
+
.send(Signal::AddTag(thread_id, key, value))
|
132
|
+
.unwrap();
|
133
|
+
true
|
134
|
+
}
|
135
|
+
|
136
|
+
#[no_mangle]
|
137
|
+
pub extern "C" fn remove_tag(thread_id: u64, key: *const c_char, value: *const c_char) -> bool {
|
138
|
+
let s = signalpass();
|
139
|
+
let key = unsafe { CStr::from_ptr(key) }.to_str().unwrap().to_owned();
|
140
|
+
let value = unsafe { CStr::from_ptr(value) }
|
141
|
+
.to_str()
|
142
|
+
.unwrap()
|
143
|
+
.to_owned();
|
144
|
+
s.inner_sender
|
145
|
+
.lock()
|
146
|
+
.unwrap()
|
147
|
+
.send(Signal::RemoveTag(thread_id, key, value))
|
148
|
+
.unwrap();
|
149
|
+
true
|
150
|
+
}
|
151
|
+
|
152
|
+
// Convert a string of tags to a Vec<(&str, &str)>
|
153
|
+
fn string_to_tags<'a>(tags: &'a str) -> Vec<(&'a str, &'a str)> {
|
154
|
+
let mut tags_vec = Vec::new();
|
155
|
+
// check if string is empty
|
156
|
+
if tags.is_empty() {
|
157
|
+
return tags_vec;
|
158
|
+
}
|
159
|
+
|
160
|
+
for tag in tags.split(',') {
|
161
|
+
let mut tag_split = tag.split('=');
|
162
|
+
let key = tag_split.next().unwrap();
|
163
|
+
let value = tag_split.next().unwrap();
|
164
|
+
tags_vec.push((key, value));
|
165
|
+
}
|
166
|
+
|
167
|
+
tags_vec
|
168
|
+
}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
[package]
|
2
|
+
name = "thread_id"
|
3
|
+
version = "0.1.0"
|
4
|
+
edition = "2021"
|
5
|
+
|
6
|
+
[lib]
|
7
|
+
name = "thread_id"
|
8
|
+
crate-type = ["cdylib"]
|
9
|
+
|
10
|
+
[dependencies]
|
11
|
+
libc = "*"
|
12
|
+
|
13
|
+
[build-dependencies]
|
14
|
+
cbindgen = "0.20.0"
|
15
|
+
|
16
|
+
[profile.release]
|
17
|
+
opt-level= "z"
|
18
|
+
debug = false
|
19
|
+
lto = true
|
20
|
+
codegen-units = 1
|
@@ -0,0 +1,163 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "shellwords"
|
4
|
+
|
5
|
+
class ThreadIdRakeCargoHelper
|
6
|
+
attr_reader :gemname
|
7
|
+
|
8
|
+
def initialize(gemname=File.basename(__dir__))
|
9
|
+
@gemname = gemname
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.command?(name)
|
13
|
+
exts = ENV["PATHEXT"] ? ENV["PATHEXT"].split(";") : [""]
|
14
|
+
ENV["PATH"].split(File::PATH_SEPARATOR).any? do |path|
|
15
|
+
exts.any? do |ext|
|
16
|
+
exe = File.join(path, "#{name}#{ext}")
|
17
|
+
File.executable?(exe) && !File.directory?(exe)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.rust_toolchain
|
23
|
+
# return env variable if set
|
24
|
+
target = ENV["RUST_TARGET"]
|
25
|
+
return target if target
|
26
|
+
|
27
|
+
str = `rustc --version --verbose`
|
28
|
+
info = str.lines.map {|l| l.chomp.split(/:\s+/, 2)}.drop(1).to_h
|
29
|
+
info["host"]
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.cargo_target_dir
|
33
|
+
return @cargo_target_dir if defined? @cargo_target_dir
|
34
|
+
|
35
|
+
str = `cargo metadata --format-version 1 --offline --no-deps --quiet`
|
36
|
+
begin
|
37
|
+
require "json"
|
38
|
+
dir = JSON.parse(str)["target_directory"]
|
39
|
+
rescue LoadError # json is usually part of the stdlib, but just in case
|
40
|
+
/"target_directory"\s*:\s*"(?<dir>[^"]*)"/ =~ str
|
41
|
+
end
|
42
|
+
@cargo_target_dir = dir || "target"
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.flags
|
46
|
+
cc_flags = Shellwords.split(RbConfig.expand(RbConfig::MAKEFILE_CONFIG["CC"].dup))
|
47
|
+
|
48
|
+
["-C", "linker=#{cc_flags.shift}",
|
49
|
+
*cc_flags.flat_map {|a| ["-C", "link-arg=#{a}"] },
|
50
|
+
"-L", "native=#{RbConfig::CONFIG["libdir"]}",
|
51
|
+
*dld_flags,
|
52
|
+
*platform_flags]
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.dld_flags
|
56
|
+
Shellwords.split(RbConfig::CONFIG["DLDFLAGS"]).flat_map do |arg|
|
57
|
+
arg = arg.gsub(/\$\((\w+)\)/) do
|
58
|
+
$1 == "DEFFILE" ? nil : RbConfig::CONFIG[name]
|
59
|
+
end.strip
|
60
|
+
next [] if arg.empty?
|
61
|
+
|
62
|
+
transform_flag(arg)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.platform_flags
|
67
|
+
return unless RbConfig::CONFIG["target_os"] =~ /mingw/i
|
68
|
+
|
69
|
+
[*Shellwords.split(RbConfig::CONFIG["LIBRUBYARG"]).flat_map {|arg| transform_flag(arg)},
|
70
|
+
"-C", "link-arg=-Wl,--dynamicbase",
|
71
|
+
"-C", "link-arg=-Wl,--disable-auto-image-base",
|
72
|
+
"-C", "link-arg=-static-libgcc"]
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.transform_flag(arg)
|
76
|
+
k, v = arg.split(/(?<=..)/, 2)
|
77
|
+
case k
|
78
|
+
when "-L"
|
79
|
+
[k, "native=#{v}"]
|
80
|
+
when "-l"
|
81
|
+
[k, v]
|
82
|
+
when "-F"
|
83
|
+
["-l", "framework=#{v}"]
|
84
|
+
else
|
85
|
+
["-C", "link_arg=#{k}#{v}"]
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def install_dir
|
90
|
+
File.expand_path(File.join("..", "..", "lib", gemname), __dir__)
|
91
|
+
end
|
92
|
+
|
93
|
+
def rust_name
|
94
|
+
prefix = "lib" unless Gem.win_platform?
|
95
|
+
suffix = if RbConfig::CONFIG["target_os"] =~ /darwin/i
|
96
|
+
".dylib"
|
97
|
+
elsif Gem.win_platform?
|
98
|
+
".dll"
|
99
|
+
else
|
100
|
+
".so"
|
101
|
+
end
|
102
|
+
"#{prefix}#{gemname}#{suffix}"
|
103
|
+
end
|
104
|
+
|
105
|
+
def ruby_name
|
106
|
+
"#{gemname}.#{RbConfig::CONFIG["DLEXT"]}"
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
task default: [:thread_id_install, :thread_id_clean]
|
112
|
+
task thread_id: [:thread_id_install, :thread_id_clean]
|
113
|
+
|
114
|
+
desc "set dev mode for subsequent task, run like `rake dev install`"
|
115
|
+
task :thread_id_dev do
|
116
|
+
@dev = true
|
117
|
+
end
|
118
|
+
|
119
|
+
desc "build gem native extension and copy to lib"
|
120
|
+
task thread_id_install: [:thread_id_cd, :thread_id_build] do
|
121
|
+
helper = ThreadIdRakeCargoHelper.new
|
122
|
+
profile_dir = @dev ? "debug" : "release"
|
123
|
+
arch_dir = RbspyRakeCargoHelper.rust_toolchain
|
124
|
+
source = File.join(ThreadIdRakeCargoHelper.cargo_target_dir, arch_dir, profile_dir, helper.rust_name)
|
125
|
+
dest = File.join(helper.install_dir, helper.ruby_name)
|
126
|
+
mkdir_p(helper.install_dir)
|
127
|
+
rm(dest) if File.exist?(dest)
|
128
|
+
cp(source, dest)
|
129
|
+
end
|
130
|
+
|
131
|
+
desc "build gem native extension"
|
132
|
+
task thread_id_build: [:thread_id_cargo, :thread_id_cd] do
|
133
|
+
sh "cargo", "rustc", *(["--locked", "--release"] unless @dev), "--target=#{RbspyRakeCargoHelper.rust_toolchain}", "--", *RbspyRakeCargoHelper.flags
|
134
|
+
end
|
135
|
+
|
136
|
+
desc "clean up release build artifacts"
|
137
|
+
task thread_id_clean: [:thread_id_cargo, :thread_id_cd] do
|
138
|
+
sh "cargo clean --release"
|
139
|
+
end
|
140
|
+
|
141
|
+
desc "clean up build artifacts"
|
142
|
+
task thread_id_clobber: [:thread_id_cargo, :thread_id_cd] do
|
143
|
+
sh "cargo clean"
|
144
|
+
end
|
145
|
+
|
146
|
+
desc "check for cargo"
|
147
|
+
task :thread_id_cargo do
|
148
|
+
raise <<-MSG unless ThreadIdRakeCargoHelper.command?("cargo")
|
149
|
+
This gem requires a Rust compiler and the `cargo' build tool to build the
|
150
|
+
gem's native extension. See https://www.rust-lang.org/tools/install for
|
151
|
+
how to install Rust. `cargo' is usually part of the Rust installation.
|
152
|
+
MSG
|
153
|
+
|
154
|
+
raise <<-MSG if Gem.win_platform? && ThreadIdRakeCargoHelper.rust_toolchain !~ /gnu/
|
155
|
+
Found Rust toolchain `#{ThreadIdRakeCargoHelper.rust_toolchain}' but the gem native
|
156
|
+
extension requires the gnu toolchain on Windows.
|
157
|
+
MSG
|
158
|
+
end
|
159
|
+
|
160
|
+
# ensure task is running in the right dir
|
161
|
+
task :thread_id_cd do
|
162
|
+
cd(__dir__) unless __dir__ == pwd
|
163
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
extern crate cbindgen;
|
2
|
+
|
3
|
+
use cbindgen::Config;
|
4
|
+
|
5
|
+
fn main() {
|
6
|
+
let bindings = {
|
7
|
+
let crate_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
|
8
|
+
let config = Config::from_file("cbindgen.toml").unwrap();
|
9
|
+
cbindgen::generate_with_config(&crate_dir, config).unwrap()
|
10
|
+
};
|
11
|
+
bindings.write_to_file("include/thread_id.h");
|
12
|
+
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# The language to output bindings in
|
2
|
+
language = "C"
|
3
|
+
documentation_style = "C"
|
4
|
+
|
5
|
+
style = "type"
|
6
|
+
|
7
|
+
# An optional name to use as an include guard
|
8
|
+
include_guard = "RBSPY_H_"
|
9
|
+
# include a comment with the version of cbindgen used to generate the file
|
10
|
+
include_version = true
|
11
|
+
|
12
|
+
# An optional string of text to output at the beginning of the generated file
|
13
|
+
header = "/* Licensed under Apache-2.0 */"
|
14
|
+
autogen_warning = "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */"
|
15
|
+
|
16
|
+
braces = "SameLine"
|
17
|
+
tab_width = 2
|
18
|
+
line_length = 80
|
19
|
+
|
20
|
+
[parse]
|
21
|
+
# Do not parse dependent crates
|
22
|
+
parse_deps = false
|
data/lib/pyroscope.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
|
3
|
+
module Rust
|
4
|
+
extend FFI::Library
|
5
|
+
ffi_lib File.expand_path(File.dirname(__FILE__)) + "/rbspy/rbspy.#{RbConfig::CONFIG["DLEXT"]}"
|
6
|
+
attach_function :initialize_agent, [:string, :string, :string, :int, :bool, :bool, :bool, :bool, :string], :bool
|
7
|
+
attach_function :add_tag, [:uint64, :string, :string], :bool
|
8
|
+
attach_function :remove_tag, [:uint64, :string, :string], :bool
|
9
|
+
attach_function :drop_agent, [], :bool
|
10
|
+
end
|
11
|
+
|
12
|
+
module Utils
|
13
|
+
extend FFI::Library
|
14
|
+
ffi_lib File.expand_path(File.dirname(__FILE__)) + "/thread_id/thread_id.#{RbConfig::CONFIG["DLEXT"]}"
|
15
|
+
attach_function :thread_id, [], :uint64
|
16
|
+
end
|
17
|
+
|
18
|
+
module Pyroscope
|
19
|
+
Config = Struct.new(:application_name, :app_name, :server_address, :auth_token, :sample_rate, :detect_subprocesses, :on_cpu, :report_pid, :report_thread_id, :log_level, :tags) do
|
20
|
+
def initialize(*)
|
21
|
+
super
|
22
|
+
self.application_name ||= ''
|
23
|
+
self.server_address ||= 'http://localhost:4040'
|
24
|
+
self.auth_token ||= ''
|
25
|
+
self.sample_rate ||= 100
|
26
|
+
self.detect_subprocesses ||= true
|
27
|
+
self.on_cpu ||= true
|
28
|
+
self.report_pid ||= false
|
29
|
+
self.report_thread_id ||= false
|
30
|
+
self.log_level ||= 'info'
|
31
|
+
self.tags ||= []
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class << self
|
36
|
+
def configure
|
37
|
+
@config = Config.new
|
38
|
+
|
39
|
+
# Pass config to the block
|
40
|
+
yield @config
|
41
|
+
|
42
|
+
Rust.initialize_agent(
|
43
|
+
@config.app_name || @config.application_name,
|
44
|
+
@config.server_address,
|
45
|
+
@config.auth_token,
|
46
|
+
@config.sample_rate,
|
47
|
+
@config.detect_subprocesses,
|
48
|
+
@config.on_cpu,
|
49
|
+
@config.report_pid,
|
50
|
+
@config.report_thread_id,
|
51
|
+
tags_to_string(@config.tags)
|
52
|
+
)
|
53
|
+
end
|
54
|
+
|
55
|
+
def tag_wrapper(tags)
|
56
|
+
tid = thread_id
|
57
|
+
_add_tags(tid, tags)
|
58
|
+
begin
|
59
|
+
yield
|
60
|
+
ensure
|
61
|
+
_remove_tags(tid, tags)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def tag(tags)
|
66
|
+
warn("deprecated. Use `Pyroscope.tag_wrapper` instead.")
|
67
|
+
end
|
68
|
+
|
69
|
+
def remove_tags(*tags)
|
70
|
+
warn("deprecated. Use `Pyroscope.tag_wrapper` instead.")
|
71
|
+
end
|
72
|
+
|
73
|
+
# convert tags object to string
|
74
|
+
def tags_to_string(tags)
|
75
|
+
tags.map { |k, v| "#{k}=#{v}" }.join(',')
|
76
|
+
end
|
77
|
+
|
78
|
+
# get thread id
|
79
|
+
def thread_id
|
80
|
+
return Utils.thread_id
|
81
|
+
end
|
82
|
+
|
83
|
+
# add tags
|
84
|
+
def _add_tags(thread_id, tags)
|
85
|
+
tags.each do |tag_name, tag_value|
|
86
|
+
Rust.add_tag(thread_id, tag_name.to_s, tag_value.to_s)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# remove tags
|
91
|
+
def _remove_tags(thread_id, tags)
|
92
|
+
tags.each do |tag_name, tag_value|
|
93
|
+
Rust.remove_tag(thread_id, tag_name.to_s, tag_value.to_s)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def drop
|
98
|
+
Rust.drop_agent
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
data/lib/rbspy/rbspy.so
ADDED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/pyroscope.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require_relative "lib/pyroscope/version"
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'pyroscope'
|
5
|
+
s.version = Pyroscope::VERSION
|
6
|
+
s.summary = 'Pyroscope'
|
7
|
+
s.description = 'Pyroscope FFI Integration for Ruby'
|
8
|
+
s.authors = ['Pyroscope Team']
|
9
|
+
s.email = ['contact@pyroscope.io']
|
10
|
+
s.homepage = 'https://pyroscope.io'
|
11
|
+
s.license = 'Apache-2.0'
|
12
|
+
|
13
|
+
# Specify which files should be added to the gem when it is released.
|
14
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
15
|
+
#s.files = Dir.chdir(__dir__) do
|
16
|
+
#`git ls-files -z`.split("\x0").reject do |f|
|
17
|
+
#(f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
|
18
|
+
#end
|
19
|
+
#end
|
20
|
+
s.files = `git ls-files -z`.split("\0").reject { |f| f =~ /^(\.|G|spec|Rakefile)/ }
|
21
|
+
|
22
|
+
s.platform = Gem::Platform::RUBY
|
23
|
+
|
24
|
+
s.required_ruby_version = ">= 2.5.9"
|
25
|
+
|
26
|
+
s.extensions = ['ext/rbspy/extconf.rb', 'ext/thread_id/extconf.rb']
|
27
|
+
|
28
|
+
s.add_dependency 'ffi'
|
29
|
+
|
30
|
+
s.add_development_dependency 'bundler'
|
31
|
+
s.add_development_dependency 'rake', '~> 13.0'
|
32
|
+
end
|
data/scripts/docker.sh
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
set -ex
|
3
|
+
|
4
|
+
BUILD_DIR="/work"
|
5
|
+
|
6
|
+
docker run \
|
7
|
+
-w /work/pyroscope_ffi/ruby/elflib/rbspy \
|
8
|
+
-v `pwd`:/work \
|
9
|
+
quay.io/pypa/${BUILD_ARCH} \
|
10
|
+
sh manylinux.sh
|
11
|
+
|
12
|
+
docker run \
|
13
|
+
-w /work/pyroscope_ffi/ruby/elflib/thread_id \
|
14
|
+
-v `pwd`:/work \
|
15
|
+
quay.io/pypa/${BUILD_ARCH} \
|
16
|
+
sh manylinux.sh
|