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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 81d23181d9828aa25373e0e5032100ac8401fb5bdf06ce786e54eda575031513
4
- data.tar.gz: c3d09e4e5179deb70fab8b26c73a39e3a29d27a037e176a6dfbe20567d0037dc
3
+ metadata.gz: 56905d725cb3ba8a3cf0b4a1342b16d66f02a878d5d7d231a66e58230d356a29
4
+ data.tar.gz: 53679ec8008bc732fc3dbbaf7a7f571ee15f8d6d90a81c5999b4139cb314dff3
5
5
  SHA512:
6
- metadata.gz: a5751e3a93da105c4c0da4a76e53c7698cf554ee4354d3acc9a95af0caa44158ce8ddd9c35c6427434a51cad1ee2482030e5ac748c7e697dec1a2484978a7a28
7
- data.tar.gz: 2d6b2cc8eb90f500bc646365894ea6d49ae1aa9b5f8ff7a41a123bb733111f7b08825851787ab49a598fea15244e81f908f9633e247a8a0bd963670ef578a4d7
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.1)
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.16.3)
11
- rake (13.2.0)
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
- 2.5.3
24
+ 4.0.9
data/README.md CHANGED
@@ -1,70 +1,24 @@
1
1
  # Pyroscope Ruby Gem
2
2
 
3
- **Pyroscope integration for Ruby**
3
+ Ruby integration for [Pyroscope](https://grafana.com/oss/pyroscope/) continuous profiling platform.
4
4
 
5
- [![license](https://img.shields.io/badge/license-Apache2.0-blue.svg)](LICENSE)
6
- ![tests](https://github.com/pyroscope-io/pyroscope-rs/workflows/Tests/badge.svg)
7
- ![build](https://github.com/pyroscope-io/pyroscope-rs/workflows/Build/badge.svg)
8
- [![Gem version](https://badge.fury.io/rb/pyroscope.svg)](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
- ### Tags
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 = "http://my-pyroscope-server:4040"
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
- ### Example
22
+ ## License
69
23
 
70
- Check out this [example ruby project in our repository](https://github.com/pyroscope-io/pyroscope/tree/main/examples/ruby) for examples of how you can use these features.
24
+ Apache-2.0
@@ -1,3 +1,3 @@
1
1
  module Pyroscope
2
- VERSION = '1.0.1'.freeze
2
+ VERSION = '1.0.2'.freeze # x-release-please-version
3
3
  end
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.io'
17
+ s.homepage = 'https://grafana.com/oss/pyroscope/'
18
18
  s.license = 'Apache-2.0'
19
19
  s.metadata = {
20
- "homepage_uri" => "https://pyroscope.io",
21
- "bug_tracker_uri" => "https://github.com/pyroscope-io/pyroscope-rs/issues",
22
- "documentation_uri" => "https://pyroscope.io/docs/ruby/",
23
- "changelog_uri" => "https://github.com/pyroscope-io/pyroscope-rs/tree/main/pyroscope_ffi/ruby/CHANGELOG.md",
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
- # Specify which files should be added to the gem when it is released.
28
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
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.1
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: 2026-02-15 00:00:00.000000000 Z
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.io
70
+ homepage: https://grafana.com/oss/pyroscope/
79
71
  licenses:
80
72
  - Apache-2.0
81
73
  metadata:
82
- homepage_uri: https://pyroscope.io
83
- bug_tracker_uri: https://github.com/pyroscope-io/pyroscope-rs/issues
84
- documentation_uri: https://pyroscope.io/docs/ruby/
85
- changelog_uri: https://github.com/pyroscope-io/pyroscope-rs/tree/main/pyroscope_ffi/ruby/CHANGELOG.md
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: 3.3.27
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
- }
@@ -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
@@ -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
- }