pyroscope 1.0.1 → 1.0.2
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 +4 -4
- data/Gemfile.lock +5 -4
- data/README.md +7 -53
- data/lib/pyroscope/version.rb +1 -1
- data/pyroscope.gemspec +7 -24
- metadata +8 -19
- data/ext/rbspy/Cargo.toml +0 -23
- data/ext/rbspy/Rakefile +0 -164
- data/ext/rbspy/build.rs +0 -12
- data/ext/rbspy/cbindgen.toml +0 -17
- data/ext/rbspy/include/rbspy.h +0 -33
- data/ext/rbspy/src/lib.rs +0 -261
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 56905d725cb3ba8a3cf0b4a1342b16d66f02a878d5d7d231a66e58230d356a29
|
|
4
|
+
data.tar.gz: 53679ec8008bc732fc3dbbaf7a7f571ee15f8d6d90a81c5999b4139cb314dff3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 66e3661210271621c7e9d2bc58b920c00eed6f74ca25d74ca09c0866948954822f5a4e85e05729372d1a940b47a31d570cf53466c25c84b1c50a67b40f520839
|
|
7
|
+
data.tar.gz: fd206c4e0e95870a58f84bd16a23b64f8d8566f323cd61870593e44a6e87a822e8a17ba60ed1220dc0e4bf60d61bacb96beed9c528d7f2e980c14165a258eb2c
|
data/Gemfile.lock
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
pyroscope (1.0.
|
|
4
|
+
pyroscope (1.0.2)
|
|
5
5
|
ffi
|
|
6
6
|
|
|
7
7
|
GEM
|
|
8
8
|
remote: https://rubygems.org/
|
|
9
9
|
specs:
|
|
10
|
-
ffi (1.
|
|
11
|
-
|
|
10
|
+
ffi (1.17.4)
|
|
11
|
+
ffi (1.17.4-x86_64-linux-gnu)
|
|
12
|
+
rake (13.3.1)
|
|
12
13
|
|
|
13
14
|
PLATFORMS
|
|
14
15
|
ruby
|
|
@@ -20,4 +21,4 @@ DEPENDENCIES
|
|
|
20
21
|
rake (~> 13.0)
|
|
21
22
|
|
|
22
23
|
BUNDLED WITH
|
|
23
|
-
|
|
24
|
+
4.0.9
|
data/README.md
CHANGED
|
@@ -1,70 +1,24 @@
|
|
|
1
1
|
# Pyroscope Ruby Gem
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Ruby integration for [Pyroscope](https://grafana.com/oss/pyroscope/) continuous profiling platform.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-

|
|
7
|
-

|
|
8
|
-
[](https://badge.fury.io/rb/pyroscope)
|
|
5
|
+
## Installation
|
|
9
6
|
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
### What is Pyroscope
|
|
13
|
-
[Pyroscope](https://github.com/pyroscope-io/pyroscope) is a tool that lets you continuously profile your applications to prevent and debug performance issues in your code. It consists of a low-overhead agent which sends data to the Pyroscope server which includes a custom-built storage engine. This allows for you to store and query any applications profiling data in an extremely efficient and cost effective way.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
### Supported platforms
|
|
17
|
-
|
|
18
|
-
| Linux | macOS | Windows | Docker |
|
|
19
|
-
|:-----:|:-----:|:-------:|:------:|
|
|
20
|
-
| ✅ | ✅ | | ✅ |
|
|
21
|
-
|
|
22
|
-
### Profiling Ruby applications
|
|
23
|
-
|
|
24
|
-
Add the `pyroscope` gem to your Gemfile:
|
|
25
|
-
|
|
26
|
-
```bash
|
|
27
|
-
bundle add pyroscope
|
|
28
7
|
```
|
|
29
|
-
|
|
30
|
-
### Basic Configuration
|
|
31
|
-
|
|
32
|
-
Add the following code to your application. If you're using rails, put this into `config/initializers` directory. This code will initialize pyroscope profiler and start profiling:
|
|
33
|
-
|
|
34
|
-
```ruby
|
|
35
|
-
require 'pyroscope'
|
|
36
|
-
|
|
37
|
-
Pyroscope.configure do |config|
|
|
38
|
-
config.application_name = "my.ruby.app" # replace this with some name for your application
|
|
39
|
-
config.server_address = "http://my-pyroscope-server:4040" # replace this with the address of your pyroscope server
|
|
40
|
-
end
|
|
8
|
+
gem install pyroscope
|
|
41
9
|
```
|
|
42
10
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
Pyroscope ruby integration provides a number of ways to tag profiling data. For example, you can provide tags when you're initializing the profiler:
|
|
11
|
+
## Usage
|
|
46
12
|
|
|
47
13
|
```ruby
|
|
48
14
|
require 'pyroscope'
|
|
49
15
|
|
|
50
16
|
Pyroscope.configure do |config|
|
|
51
17
|
config.application_name = "my.ruby.app"
|
|
52
|
-
config.server_address
|
|
53
|
-
|
|
54
|
-
config.tags = {
|
|
55
|
-
"hostname" => ENV["HOSTNAME"],
|
|
56
|
-
}
|
|
57
|
-
end
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
or you can dynamically tag certain parts of your code:
|
|
61
|
-
|
|
62
|
-
```ruby
|
|
63
|
-
Pyroscope.tag_wrapper({ "controller": "slow_controller_i_want_to_profile" }) do
|
|
64
|
-
slow_code
|
|
18
|
+
config.server_address = "http://localhost:4040"
|
|
65
19
|
end
|
|
66
20
|
```
|
|
67
21
|
|
|
68
|
-
|
|
22
|
+
## License
|
|
69
23
|
|
|
70
|
-
|
|
24
|
+
Apache-2.0
|
data/lib/pyroscope/version.rb
CHANGED
data/pyroscope.gemspec
CHANGED
|
@@ -14,42 +14,25 @@ Gem::Specification.new do |s|
|
|
|
14
14
|
s.description = 'Pyroscope FFI Integration for Ruby'
|
|
15
15
|
s.authors = ['Pyroscope Team']
|
|
16
16
|
s.email = ['contact@pyroscope.io']
|
|
17
|
-
s.homepage = 'https://pyroscope
|
|
17
|
+
s.homepage = 'https://grafana.com/oss/pyroscope/'
|
|
18
18
|
s.license = 'Apache-2.0'
|
|
19
19
|
s.metadata = {
|
|
20
|
-
"homepage_uri" => "https://pyroscope
|
|
21
|
-
"bug_tracker_uri" => "https://github.com/
|
|
22
|
-
"documentation_uri" => "https://
|
|
23
|
-
"
|
|
24
|
-
"source_code_uri" => "https://github.com/pyroscope-io/pyroscope-rs/tree/main/pyroscope_ffi/ruby",
|
|
20
|
+
"homepage_uri" => "https://grafana.com/oss/pyroscope/",
|
|
21
|
+
"bug_tracker_uri" => "https://github.com/grafana/pyroscope-ruby/issues",
|
|
22
|
+
"documentation_uri" => "https://grafana.com/docs/pyroscope/latest/configure-client/language-sdks/ruby/",
|
|
23
|
+
"source_code_uri" => "https://github.com/grafana/pyroscope-ruby",
|
|
25
24
|
}
|
|
26
25
|
|
|
27
|
-
#
|
|
28
|
-
#
|
|
29
|
-
#s.files = Dir.chdir(__dir__) do
|
|
30
|
-
#`git ls-files -z`.split("\x0").reject do |f|
|
|
31
|
-
#(f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
|
|
32
|
-
#end
|
|
33
|
-
#end
|
|
34
|
-
# s.files = `git ls-files -z`.split("\0").reject { |f| f =~ /^(\.|G|spec|Rakefile)/ }
|
|
26
|
+
# TODO: s.files is incomplete — ext/rbspy/ sources are missing, so building
|
|
27
|
+
# the gem from source does not work. See https://github.com/grafana/pyroscope-ruby/issues/2
|
|
35
28
|
s.files = [
|
|
36
29
|
"Gemfile",
|
|
37
30
|
"Gemfile.lock",
|
|
38
31
|
"LICENSE",
|
|
39
|
-
# "Makefile",
|
|
40
32
|
"README.md",
|
|
41
|
-
# "Rakefile",
|
|
42
|
-
"ext/rbspy/Cargo.toml",
|
|
43
|
-
"ext/rbspy/Rakefile",
|
|
44
|
-
"ext/rbspy/build.rs",
|
|
45
|
-
"ext/rbspy/cbindgen.toml",
|
|
46
|
-
"ext/rbspy/extconf.rb",
|
|
47
|
-
"ext/rbspy/include/rbspy.h",
|
|
48
|
-
"ext/rbspy/src/lib.rs",
|
|
49
33
|
"lib/pyroscope.rb",
|
|
50
34
|
"lib/pyroscope/version.rb",
|
|
51
35
|
"pyroscope.gemspec",
|
|
52
|
-
# "scripts/tests/test.rb",
|
|
53
36
|
]
|
|
54
37
|
s.platform = Gem::Platform::RUBY
|
|
55
38
|
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: pyroscope
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Pyroscope Team
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: ffi
|
|
@@ -24,7 +23,6 @@ dependencies:
|
|
|
24
23
|
- - ">="
|
|
25
24
|
- !ruby/object:Gem::Version
|
|
26
25
|
version: '0'
|
|
27
|
-
force_ruby_platform: false
|
|
28
26
|
- !ruby/object:Gem::Dependency
|
|
29
27
|
name: bundler
|
|
30
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -65,26 +63,18 @@ files:
|
|
|
65
63
|
- Gemfile.lock
|
|
66
64
|
- LICENSE
|
|
67
65
|
- README.md
|
|
68
|
-
- ext/rbspy/Cargo.toml
|
|
69
|
-
- ext/rbspy/Rakefile
|
|
70
|
-
- ext/rbspy/build.rs
|
|
71
|
-
- ext/rbspy/cbindgen.toml
|
|
72
66
|
- ext/rbspy/extconf.rb
|
|
73
|
-
- ext/rbspy/include/rbspy.h
|
|
74
|
-
- ext/rbspy/src/lib.rs
|
|
75
67
|
- lib/pyroscope.rb
|
|
76
68
|
- lib/pyroscope/version.rb
|
|
77
69
|
- pyroscope.gemspec
|
|
78
|
-
homepage: https://pyroscope
|
|
70
|
+
homepage: https://grafana.com/oss/pyroscope/
|
|
79
71
|
licenses:
|
|
80
72
|
- Apache-2.0
|
|
81
73
|
metadata:
|
|
82
|
-
homepage_uri: https://pyroscope
|
|
83
|
-
bug_tracker_uri: https://github.com/
|
|
84
|
-
documentation_uri: https://
|
|
85
|
-
|
|
86
|
-
source_code_uri: https://github.com/pyroscope-io/pyroscope-rs/tree/main/pyroscope_ffi/ruby
|
|
87
|
-
post_install_message:
|
|
74
|
+
homepage_uri: https://grafana.com/oss/pyroscope/
|
|
75
|
+
bug_tracker_uri: https://github.com/grafana/pyroscope-ruby/issues
|
|
76
|
+
documentation_uri: https://grafana.com/docs/pyroscope/latest/configure-client/language-sdks/ruby/
|
|
77
|
+
source_code_uri: https://github.com/grafana/pyroscope-ruby
|
|
88
78
|
rdoc_options: []
|
|
89
79
|
require_paths:
|
|
90
80
|
- lib
|
|
@@ -99,8 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
99
89
|
- !ruby/object:Gem::Version
|
|
100
90
|
version: '0'
|
|
101
91
|
requirements: []
|
|
102
|
-
rubygems_version:
|
|
103
|
-
signing_key:
|
|
92
|
+
rubygems_version: 4.0.6
|
|
104
93
|
specification_version: 4
|
|
105
94
|
summary: Pyroscope
|
|
106
95
|
test_files: []
|
data/ext/rbspy/Cargo.toml
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
[package]
|
|
2
|
-
name = "ffiruby"
|
|
3
|
-
version = "0.0.1"
|
|
4
|
-
edition = "2021"
|
|
5
|
-
rust-version = "1.64"
|
|
6
|
-
|
|
7
|
-
[lib]
|
|
8
|
-
name = "rbspy"
|
|
9
|
-
crate-type = ["cdylib"]
|
|
10
|
-
|
|
11
|
-
[dependencies]
|
|
12
|
-
pyroscope = { path = "../../../../" }
|
|
13
|
-
rbspy = { version="0.42" }
|
|
14
|
-
remoteprocess = "0.5.0"
|
|
15
|
-
anyhow = "1.0"
|
|
16
|
-
# todo remove this dependency
|
|
17
|
-
pretty_env_logger = "0.5"
|
|
18
|
-
log = "0.4"
|
|
19
|
-
libc = "0.2.180"
|
|
20
|
-
|
|
21
|
-
[build-dependencies]
|
|
22
|
-
cbindgen = "0.29"
|
|
23
|
-
|
data/ext/rbspy/Rakefile
DELETED
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "shellwords"
|
|
4
|
-
|
|
5
|
-
class RbspyRakeCargoHelper
|
|
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
|
-
]
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def self.dld_flags
|
|
57
|
-
Shellwords.split(RbConfig::CONFIG["DLDFLAGS"]).flat_map do |arg|
|
|
58
|
-
arg = arg.gsub(/\$\((\w+)\)/) do
|
|
59
|
-
$1 == "DEFFILE" ? nil : RbConfig::CONFIG[name]
|
|
60
|
-
end.strip
|
|
61
|
-
next [] if arg.empty?
|
|
62
|
-
|
|
63
|
-
transform_flag(arg)
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def self.platform_flags
|
|
68
|
-
return unless RbConfig::CONFIG["target_os"] =~ /mingw/i
|
|
69
|
-
|
|
70
|
-
[*Shellwords.split(RbConfig::CONFIG["LIBRUBYARG"]).flat_map {|arg| transform_flag(arg)},
|
|
71
|
-
"-C", "link-arg=-Wl,--dynamicbase",
|
|
72
|
-
"-C", "link-arg=-Wl,--disable-auto-image-base",
|
|
73
|
-
"-C", "link-arg=-static-libgcc"]
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def self.transform_flag(arg)
|
|
77
|
-
k, v = arg.split(/(?<=..)/, 2)
|
|
78
|
-
case k
|
|
79
|
-
when "-L"
|
|
80
|
-
[k, "native=#{v}"]
|
|
81
|
-
when "-l"
|
|
82
|
-
[k, v]
|
|
83
|
-
when "-F"
|
|
84
|
-
["-l", "framework=#{v}"]
|
|
85
|
-
else
|
|
86
|
-
["-C", "link_arg=#{k}#{v}"]
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def install_dir
|
|
91
|
-
File.expand_path(File.join("..", "..", "lib", gemname), __dir__)
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
def rust_name
|
|
95
|
-
prefix = "lib" unless Gem.win_platform?
|
|
96
|
-
suffix = if RbConfig::CONFIG["target_os"] =~ /darwin/i
|
|
97
|
-
".dylib"
|
|
98
|
-
elsif Gem.win_platform?
|
|
99
|
-
".dll"
|
|
100
|
-
else
|
|
101
|
-
".so"
|
|
102
|
-
end
|
|
103
|
-
"#{prefix}#{gemname}#{suffix}"
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
def ruby_name
|
|
107
|
-
"#{gemname}.#{RbConfig::CONFIG["DLEXT"]}"
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
task default: [:rbspy_install, :rbspy_clean]
|
|
113
|
-
task rbspy: [:rbspy_install, :rbspy_clean]
|
|
114
|
-
|
|
115
|
-
desc "set dev mode for subsequent task, run like `rake dev install`"
|
|
116
|
-
task :rbspy_dev do
|
|
117
|
-
@dev = true
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
desc "build gem native extension and copy to lib"
|
|
121
|
-
task rbspy_install: [:rbspy_cd, :rbspy_build] do
|
|
122
|
-
helper = RbspyRakeCargoHelper.new
|
|
123
|
-
profile_dir = @dev ? "debug" : "release"
|
|
124
|
-
arch_dir = RbspyRakeCargoHelper.rust_toolchain
|
|
125
|
-
source = File.join(RbspyRakeCargoHelper.cargo_target_dir, arch_dir, profile_dir, helper.rust_name)
|
|
126
|
-
dest = File.join(helper.install_dir, helper.ruby_name)
|
|
127
|
-
mkdir_p(helper.install_dir)
|
|
128
|
-
rm(dest) if File.exist?(dest)
|
|
129
|
-
cp(source, dest)
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
desc "build gem native extension"
|
|
133
|
-
task rbspy_build: [:rbspy_cargo, :rbspy_cd] do
|
|
134
|
-
sh "cargo", "rustc", *(["--locked", "--release"] unless @dev), "--target=#{RbspyRakeCargoHelper.rust_toolchain}", "--", *RbspyRakeCargoHelper.flags
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
desc "clean up release build artifacts"
|
|
138
|
-
task rbspy_clean: [:rbspy_cargo, :rbspy_cd] do
|
|
139
|
-
sh "cargo clean --release"
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
desc "clean up build artifacts"
|
|
143
|
-
task rbspy_clobber: [:rbspy_cargo, :rbspy_cd] do
|
|
144
|
-
sh "cargo clean"
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
desc "check for cargo"
|
|
148
|
-
task :rbspy_cargo do
|
|
149
|
-
raise <<-MSG unless RbspyRakeCargoHelper.command?("cargo")
|
|
150
|
-
This gem requires a Rust compiler and the `cargo' build tool to build the
|
|
151
|
-
gem's native extension. See https://www.rust-lang.org/tools/install for
|
|
152
|
-
how to install Rust. `cargo' is usually part of the Rust installation.
|
|
153
|
-
MSG
|
|
154
|
-
|
|
155
|
-
raise <<-MSG if Gem.win_platform? && RbspyRakeCargoHelper.rust_toolchain !~ /gnu/
|
|
156
|
-
Found Rust toolchain `#{RbspyRakeCargoHelper.rust_toolchain}' but the gem native
|
|
157
|
-
extension requires the gnu toolchain on Windows.
|
|
158
|
-
MSG
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
# ensure task is running in the right dir
|
|
162
|
-
task :rbspy_cd do
|
|
163
|
-
cd(__dir__) unless __dir__ == pwd
|
|
164
|
-
end
|
data/ext/rbspy/build.rs
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
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/rbspy.h");
|
|
12
|
-
}
|
data/ext/rbspy/cbindgen.toml
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
language = "C"
|
|
2
|
-
documentation_style = "C"
|
|
3
|
-
|
|
4
|
-
style = "type"
|
|
5
|
-
|
|
6
|
-
include_guard = "RBSPY_H_"
|
|
7
|
-
include_version = false
|
|
8
|
-
|
|
9
|
-
header = "/* Licensed under Apache-2.0 */"
|
|
10
|
-
autogen_warning = "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */"
|
|
11
|
-
|
|
12
|
-
braces = "SameLine"
|
|
13
|
-
tab_width = 2
|
|
14
|
-
line_length = 80
|
|
15
|
-
|
|
16
|
-
[parse]
|
|
17
|
-
parse_deps = false
|
data/ext/rbspy/include/rbspy.h
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/* Licensed under Apache-2.0 */
|
|
2
|
-
|
|
3
|
-
#ifndef RBSPY_H_
|
|
4
|
-
#define RBSPY_H_
|
|
5
|
-
|
|
6
|
-
/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */
|
|
7
|
-
|
|
8
|
-
#include <stdarg.h>
|
|
9
|
-
#include <stdbool.h>
|
|
10
|
-
#include <stdint.h>
|
|
11
|
-
#include <stdlib.h>
|
|
12
|
-
|
|
13
|
-
bool initialize_logging(uint32_t logging_level);
|
|
14
|
-
|
|
15
|
-
bool initialize_agent(const char *application_name,
|
|
16
|
-
const char *server_address,
|
|
17
|
-
const char *basic_auth_user,
|
|
18
|
-
const char *basic_auth_password,
|
|
19
|
-
uint32_t sample_rate,
|
|
20
|
-
bool oncpu,
|
|
21
|
-
bool report_pid,
|
|
22
|
-
bool report_thread_id,
|
|
23
|
-
const char *tags,
|
|
24
|
-
const char *tenant_id,
|
|
25
|
-
const char *http_headers_json);
|
|
26
|
-
|
|
27
|
-
bool drop_agent(void);
|
|
28
|
-
|
|
29
|
-
bool add_thread_tag(const char *key, const char *value);
|
|
30
|
-
|
|
31
|
-
bool remove_thread_tag(const char *key, const char *value);
|
|
32
|
-
|
|
33
|
-
#endif /* RBSPY_H_ */
|
data/ext/rbspy/src/lib.rs
DELETED
|
@@ -1,261 +0,0 @@
|
|
|
1
|
-
mod backend;
|
|
2
|
-
|
|
3
|
-
use rbspy::sampler::Sampler;
|
|
4
|
-
use remoteprocess::Pid;
|
|
5
|
-
use std::env;
|
|
6
|
-
use std::ffi::CStr;
|
|
7
|
-
use std::os::raw::c_char;
|
|
8
|
-
|
|
9
|
-
use crate::backend::Rbspy;
|
|
10
|
-
use pyroscope;
|
|
11
|
-
use pyroscope::backend::{BackendConfig, BackendImpl, Report, StackFrame, Tag};
|
|
12
|
-
use pyroscope::pyroscope::PyroscopeAgentBuilder;
|
|
13
|
-
|
|
14
|
-
const LOG_TAG: &str = "Pyroscope::rbspy::ffi";
|
|
15
|
-
const RBSPY_NAME: &str = "rbspy";
|
|
16
|
-
const RBSPY_VERSION: &str = "1.0.1";
|
|
17
|
-
|
|
18
|
-
pub fn transform_report(report: Report) -> Report {
|
|
19
|
-
let cwd = env::current_dir().unwrap();
|
|
20
|
-
let cwd = cwd.to_str().unwrap_or("");
|
|
21
|
-
|
|
22
|
-
let data = report
|
|
23
|
-
.data
|
|
24
|
-
.iter()
|
|
25
|
-
.map(|(stacktrace, count)| {
|
|
26
|
-
let new_frames = stacktrace
|
|
27
|
-
.frames
|
|
28
|
-
.iter()
|
|
29
|
-
.map(|frame| {
|
|
30
|
-
let frame = frame.to_owned();
|
|
31
|
-
let mut s = frame.filename.unwrap();
|
|
32
|
-
match s.find(cwd) {
|
|
33
|
-
Some(i) => {
|
|
34
|
-
s = s[(i + cwd.len() + 1)..].to_string();
|
|
35
|
-
}
|
|
36
|
-
None => match s.find("/gems/") {
|
|
37
|
-
Some(i) => {
|
|
38
|
-
s = s[(i + 1)..].to_string();
|
|
39
|
-
}
|
|
40
|
-
None => match s.find("/ruby/") {
|
|
41
|
-
Some(i) => {
|
|
42
|
-
s = s[(i + 6)..].to_string();
|
|
43
|
-
match s.find("/") {
|
|
44
|
-
Some(i) => {
|
|
45
|
-
s = s[(i + 1)..].to_string();
|
|
46
|
-
}
|
|
47
|
-
None => {}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
None => {}
|
|
51
|
-
},
|
|
52
|
-
},
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// something
|
|
56
|
-
StackFrame::new(
|
|
57
|
-
frame.module,
|
|
58
|
-
frame.name,
|
|
59
|
-
Some(s.to_string()),
|
|
60
|
-
frame.relative_path,
|
|
61
|
-
frame.absolute_path,
|
|
62
|
-
frame.line,
|
|
63
|
-
)
|
|
64
|
-
})
|
|
65
|
-
.collect();
|
|
66
|
-
|
|
67
|
-
let mut mystack = stacktrace.to_owned();
|
|
68
|
-
|
|
69
|
-
mystack.frames = new_frames;
|
|
70
|
-
|
|
71
|
-
(mystack, count.to_owned())
|
|
72
|
-
})
|
|
73
|
-
.collect();
|
|
74
|
-
|
|
75
|
-
let new_report = Report::new(data).metadata(report.metadata.clone());
|
|
76
|
-
|
|
77
|
-
new_report
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
#[no_mangle]
|
|
81
|
-
pub extern "C" fn initialize_logging(logging_level: u32) -> bool {
|
|
82
|
-
// Force rustc to display the log messages in the console.
|
|
83
|
-
match logging_level {
|
|
84
|
-
50 => {
|
|
85
|
-
std::env::set_var("RUST_LOG", "error");
|
|
86
|
-
}
|
|
87
|
-
40 => {
|
|
88
|
-
std::env::set_var("RUST_LOG", "warn");
|
|
89
|
-
}
|
|
90
|
-
30 => {
|
|
91
|
-
std::env::set_var("RUST_LOG", "info");
|
|
92
|
-
}
|
|
93
|
-
20 => {
|
|
94
|
-
std::env::set_var("RUST_LOG", "debug");
|
|
95
|
-
}
|
|
96
|
-
10 => {
|
|
97
|
-
std::env::set_var("RUST_LOG", "trace");
|
|
98
|
-
}
|
|
99
|
-
_ => {
|
|
100
|
-
std::env::set_var("RUST_LOG", "debug");
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Initialize the logger.
|
|
105
|
-
pretty_env_logger::init_timed();
|
|
106
|
-
|
|
107
|
-
true
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
#[no_mangle]
|
|
111
|
-
pub extern "C" fn initialize_agent(
|
|
112
|
-
application_name: *const c_char,
|
|
113
|
-
server_address: *const c_char,
|
|
114
|
-
basic_auth_user: *const c_char,
|
|
115
|
-
basic_auth_password: *const c_char,
|
|
116
|
-
sample_rate: u32,
|
|
117
|
-
oncpu: bool,
|
|
118
|
-
report_pid: bool,
|
|
119
|
-
report_thread_id: bool,
|
|
120
|
-
tags: *const c_char,
|
|
121
|
-
tenant_id: *const c_char,
|
|
122
|
-
http_headers_json: *const c_char,
|
|
123
|
-
) -> bool {
|
|
124
|
-
let application_name = unsafe { CStr::from_ptr(application_name) }
|
|
125
|
-
.to_str()
|
|
126
|
-
.unwrap()
|
|
127
|
-
.to_string();
|
|
128
|
-
|
|
129
|
-
let server_address = unsafe { CStr::from_ptr(server_address) }
|
|
130
|
-
.to_str()
|
|
131
|
-
.unwrap()
|
|
132
|
-
.to_string();
|
|
133
|
-
|
|
134
|
-
let basic_auth_user = unsafe { CStr::from_ptr(basic_auth_user) }
|
|
135
|
-
.to_str()
|
|
136
|
-
.unwrap()
|
|
137
|
-
.to_string();
|
|
138
|
-
|
|
139
|
-
let basic_auth_password = unsafe { CStr::from_ptr(basic_auth_password) }
|
|
140
|
-
.to_str()
|
|
141
|
-
.unwrap()
|
|
142
|
-
.to_string();
|
|
143
|
-
|
|
144
|
-
let tags_string = unsafe { CStr::from_ptr(tags) }
|
|
145
|
-
.to_str()
|
|
146
|
-
.unwrap()
|
|
147
|
-
.to_string();
|
|
148
|
-
|
|
149
|
-
let tenant_id = unsafe { CStr::from_ptr(tenant_id) }
|
|
150
|
-
.to_str()
|
|
151
|
-
.unwrap()
|
|
152
|
-
.to_string();
|
|
153
|
-
|
|
154
|
-
let http_headers_json = unsafe { CStr::from_ptr(http_headers_json) }
|
|
155
|
-
.to_str()
|
|
156
|
-
.unwrap()
|
|
157
|
-
.to_string();
|
|
158
|
-
|
|
159
|
-
let pid = std::process::id();
|
|
160
|
-
|
|
161
|
-
let backend_config = BackendConfig {
|
|
162
|
-
report_thread_id,
|
|
163
|
-
report_thread_name: false,
|
|
164
|
-
report_pid,
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
let sampler = Sampler::new(pid as Pid, sample_rate, false, None, false, None, oncpu);
|
|
168
|
-
|
|
169
|
-
let tags_ref = tags_string.as_str();
|
|
170
|
-
let tags = string_to_tags(tags_ref);
|
|
171
|
-
let rbspy = BackendImpl::new(Box::new(Rbspy::new(sampler, sample_rate, backend_config)));
|
|
172
|
-
|
|
173
|
-
let mut agent_builder = PyroscopeAgentBuilder::new(
|
|
174
|
-
server_address,
|
|
175
|
-
application_name,
|
|
176
|
-
sample_rate,
|
|
177
|
-
RBSPY_NAME,
|
|
178
|
-
RBSPY_VERSION,
|
|
179
|
-
rbspy,
|
|
180
|
-
)
|
|
181
|
-
.func(transform_report)
|
|
182
|
-
.tags(tags);
|
|
183
|
-
|
|
184
|
-
if basic_auth_user != "" && basic_auth_password != "" {
|
|
185
|
-
agent_builder = agent_builder.basic_auth(basic_auth_user, basic_auth_password);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
if tenant_id != "" {
|
|
189
|
-
agent_builder = agent_builder.tenant_id(tenant_id);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
let http_headers = pyroscope::pyroscope::parse_http_headers_json(http_headers_json);
|
|
193
|
-
match http_headers {
|
|
194
|
-
Ok(http_headers) => {
|
|
195
|
-
agent_builder = agent_builder.http_headers(http_headers);
|
|
196
|
-
}
|
|
197
|
-
Err(e) => match e {
|
|
198
|
-
pyroscope::PyroscopeError::Json(e) => {
|
|
199
|
-
log::error!(target: LOG_TAG, "parse_http_headers_json error {}", e);
|
|
200
|
-
}
|
|
201
|
-
pyroscope::PyroscopeError::AdHoc(e) => {
|
|
202
|
-
log::error!(target: LOG_TAG, "parse_http_headers_json {}", e);
|
|
203
|
-
}
|
|
204
|
-
_ => {}
|
|
205
|
-
},
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
pyroscope::ffikit::run(agent_builder).is_ok()
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
#[no_mangle]
|
|
212
|
-
pub extern "C" fn drop_agent() -> bool {
|
|
213
|
-
pyroscope::ffikit::send(pyroscope::ffikit::Signal::Kill).is_ok()
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
#[no_mangle]
|
|
217
|
-
pub extern "C" fn add_thread_tag(key: *const c_char, value: *const c_char) -> bool {
|
|
218
|
-
let key = unsafe { CStr::from_ptr(key) }.to_str().unwrap().to_owned();
|
|
219
|
-
let value = unsafe { CStr::from_ptr(value) }
|
|
220
|
-
.to_str()
|
|
221
|
-
.unwrap()
|
|
222
|
-
.to_owned();
|
|
223
|
-
|
|
224
|
-
pyroscope::ffikit::send(pyroscope::ffikit::Signal::AddThreadTag(
|
|
225
|
-
backend::self_thread_id(),
|
|
226
|
-
Tag { key, value },
|
|
227
|
-
))
|
|
228
|
-
.is_ok()
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
#[no_mangle]
|
|
232
|
-
pub extern "C" fn remove_thread_tag(key: *const c_char, value: *const c_char) -> bool {
|
|
233
|
-
let key = unsafe { CStr::from_ptr(key) }.to_str().unwrap().to_owned();
|
|
234
|
-
let value = unsafe { CStr::from_ptr(value) }
|
|
235
|
-
.to_str()
|
|
236
|
-
.unwrap()
|
|
237
|
-
.to_owned();
|
|
238
|
-
|
|
239
|
-
pyroscope::ffikit::send(pyroscope::ffikit::Signal::RemoveThreadTag(
|
|
240
|
-
backend::self_thread_id(),
|
|
241
|
-
Tag { key, value },
|
|
242
|
-
))
|
|
243
|
-
.is_ok()
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
fn string_to_tags<'a>(tags: &'a str) -> Vec<(&'a str, &'a str)> {
|
|
247
|
-
let mut tags_vec = Vec::new();
|
|
248
|
-
// check if string is empty
|
|
249
|
-
if tags.is_empty() {
|
|
250
|
-
return tags_vec;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
for tag in tags.split(',') {
|
|
254
|
-
let mut tag_split = tag.split('=');
|
|
255
|
-
let key = tag_split.next().unwrap();
|
|
256
|
-
let value = tag_split.next().unwrap();
|
|
257
|
-
tags_vec.push((key, value));
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
tags_vec
|
|
261
|
-
}
|