pyroscope 0.3.2-x86_64-darwin → 0.4.0-x86_64-darwin

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: 04463bc7a3a932eef056c8d20e677b042fc921b5df2df4296279fd34c7dc9bfd
4
- data.tar.gz: 4fa8c6865eea79b89781600691c06c63a1160a66b7d4815881fc4ae4be37c622
3
+ metadata.gz: 636eab1f55b6b4961f65f17715ea677e97c7f3d09db8f23a01f61efc05eb25d5
4
+ data.tar.gz: 15caf72125e714c5bebcbaa632ceccc805a03ebffef76b8612bf81f83fed2a40
5
5
  SHA512:
6
- metadata.gz: 6b23669db4195412878522947572126877e33fa0596f24086efdd80b2ad6f46874520ea3201687a78d1f1da8093ad77493eb0b0390ad5a4aeab7cdd280866c5c
7
- data.tar.gz: 4bdbccad469ba8adf06b181b60544faa04b634d9bfeedce3c048ca54fd6aa645a460cf2b79abd4f307353fa79f02ffcdc9ed69cce545c1bfa91813fc13b3b191
6
+ metadata.gz: 5a286732b2b19067b530a354fceba3612c450f7b675d77711d1b88a60492a74a5f2f5133edd8e527b2ef46b08862d61ba450c64632d615fb84fa58ac5571aa6b
7
+ data.tar.gz: 273e2663bbd27c73265baa46442ebd8fe05695cdcb493ad14e84c555c42f14d903c40625b8db01c9f47317dfc7b2393d39f5ee315e500c3540bffafc78007b36
data/README.md CHANGED
@@ -1,57 +1,71 @@
1
- Pyroscope Ruby Integration --Beta--
2
- =====================================
1
+ # Pyroscope Ruby Gem
3
2
 
4
- **note**: This is a beta release. It requires local compilation, might be
5
- buggy and is frequently updated. For the initial implementation, find it [here](https://github.com/pyroscope-io/pyroscope-ruby). Please report any [issues](https://github.com/pyroscope-io/pyroscope-rs/issues).
3
+ **Pyroscope integration for Ruby**
6
4
 
7
- ## Installation
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)
8
9
 
9
- 1. You need the Rust toolchain to compile the library locally. To install
10
- Rust:
10
+ ---
11
11
 
12
- ```
13
- curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain stable -y
14
- export PATH=$PATH:/root/.cargo/bin
15
- ```
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.
16
14
 
17
- 2. Building/Insalling from Rubygems
18
15
 
19
- ```
20
- gem install pyroscope_beta
21
- ```
16
+ ### Supported platforms
22
17
 
23
- 3. Building/Installing from source
18
+ | Linux | macOS | Windows | Docker |
19
+ |:-----:|:-----:|:-------:|:------:|
20
+ | ✅ | ✅ | | ✅ |
24
21
 
25
- Change directory to `pyroscope_ffi/ruby` and run
22
+ ### Profiling Ruby applications
26
23
 
24
+ Add the `pyroscope` gem to your Gemfile:
25
+
26
+ ```bash
27
+ bundle add pyroscope
27
28
  ```
28
- gem build pyroscope.gemspec
29
- gem install ./pyroscope.gemspec
30
- ```
31
29
 
32
- ## Configuration
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
33
 
34
- Configuration is similar to the old package except for `application_name`:
34
+ ```ruby
35
+ require 'pyroscope'
35
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
+ # config.auth_token = "{YOUR_API_KEY}" # optionally, if authentication is enabled, specify the API key
41
+ end
36
42
  ```
37
- require 'pyroscope_beta'
43
+
44
+ ### Tags
45
+
46
+ Pyroscope ruby integration provides a number of ways to tag profiling data. For example, you can provide tags when you're initializing the profiler:
47
+
48
+ ```ruby
49
+ require 'pyroscope'
38
50
 
39
51
  Pyroscope.configure do |config|
40
- config.application_name = "ruby.app"
41
- config.server_address = "http://localhost:4040"
42
- config.detect_subprocesses = true
52
+ config.application_name = "my.ruby.app"
53
+ config.server_address = "http://my-pyroscope-server:4040"
54
+
43
55
  config.tags = {
44
- :key => "value",
56
+ "hostname" => ENV["HOSTNAME"],
45
57
  }
46
58
  end
47
59
  ```
48
60
 
49
- ## Adding tags
61
+ or you can dynamically tag certain parts of your code:
50
62
 
51
- Tags passed to configure are global. To tag code locally, you can use:
52
-
53
- ```
54
- Pyroscope.tag_wrapper({"profile": "profile-1"}) do
55
- // Tagged profile
63
+ ```ruby
64
+ Pyroscope.tag_wrapper({ "controller": "slow_controller_i_want_to_profile" }) do
65
+ slow_code
56
66
  end
57
67
  ```
68
+
69
+ ### Example
70
+
71
+ 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.
data/ext/rbspy/src/lib.rs CHANGED
@@ -1,12 +1,15 @@
1
- use ffikit::Signal;
2
- use pyroscope::backend::{Report, StackFrame, Tag};
3
- use pyroscope::PyroscopeAgent;
4
- use pyroscope_rbspy::{rbspy_backend, RbspyConfig};
5
1
  use std::collections::hash_map::DefaultHasher;
2
+ use std::env;
6
3
  use std::ffi::CStr;
7
4
  use std::hash::Hasher;
8
5
  use std::os::raw::c_char;
9
- use std::env;
6
+ use std::str::FromStr;
7
+
8
+ use ffikit::Signal;
9
+ use pyroscope_rbspy::{rbspy_backend, RbspyConfig};
10
+
11
+ use pyroscope::{pyroscope::Compression, PyroscopeAgent};
12
+ use pyroscope::backend::{Report, StackFrame, Tag};
10
13
 
11
14
  pub fn transform_report(report: Report) -> Report {
12
15
  let cwd = env::current_dir().unwrap();
@@ -24,31 +27,25 @@ pub fn transform_report(report: Report) -> Report {
24
27
  let mut s = frame.filename.unwrap();
25
28
  match s.find(cwd) {
26
29
  Some(i) => {
27
- s = s[(i+cwd.len()+1)..].to_string();
30
+ s = s[(i + cwd.len() + 1)..].to_string();
28
31
  }
29
- None => {
30
- match s.find("/gems/") {
32
+ None => match s.find("/gems/") {
33
+ Some(i) => {
34
+ s = s[(i + 1)..].to_string();
35
+ }
36
+ None => match s.find("/ruby/") {
31
37
  Some(i) => {
32
- s = s[(i+1)..].to_string();
33
- }
34
- None => {
35
- match s.find("/ruby/") {
38
+ s = s[(i + 6)..].to_string();
39
+ match s.find("/") {
36
40
  Some(i) => {
37
- s = s[(i+6)..].to_string();
38
- match s.find("/") {
39
- Some(i) => {
40
- s = s[(i+1)..].to_string();
41
- }
42
- None => {
43
- }
44
- }
45
- }
46
- None => {
41
+ s = s[(i + 1)..].to_string();
47
42
  }
43
+ None => {}
48
44
  }
49
45
  }
50
- }
51
- }
46
+ None => {}
47
+ },
48
+ },
52
49
  }
53
50
 
54
51
  // something
@@ -76,11 +73,41 @@ pub fn transform_report(report: Report) -> Report {
76
73
  new_report
77
74
  }
78
75
 
76
+ #[no_mangle]
77
+ pub extern "C" fn initialize_logging(logging_level: u32) -> bool {
78
+ // Force rustc to display the log messages in the console.
79
+ match logging_level {
80
+ 50 => {
81
+ std::env::set_var("RUST_LOG", "error");
82
+ }
83
+ 40 => {
84
+ std::env::set_var("RUST_LOG", "warn");
85
+ }
86
+ 30 => {
87
+ std::env::set_var("RUST_LOG", "info");
88
+ }
89
+ 20 => {
90
+ std::env::set_var("RUST_LOG", "debug");
91
+ }
92
+ 10 => {
93
+ std::env::set_var("RUST_LOG", "trace");
94
+ }
95
+ _ => {
96
+ std::env::set_var("RUST_LOG", "debug");
97
+ }
98
+ }
99
+
100
+ // Initialize the logger.
101
+ pretty_env_logger::init_timed();
102
+
103
+ true
104
+ }
105
+
79
106
  #[no_mangle]
80
107
  pub extern "C" fn initialize_agent(
81
108
  application_name: *const c_char, server_address: *const c_char, auth_token: *const c_char,
82
- sample_rate: u32, detect_subprocesses: bool, on_cpu: bool, report_pid: bool,
83
- report_thread_id: bool, tags: *const c_char,
109
+ sample_rate: u32, detect_subprocesses: bool, oncpu: bool, report_pid: bool,
110
+ report_thread_id: bool, tags: *const c_char, compression: *const c_char
84
111
  ) -> bool {
85
112
  // Initialize FFIKit
86
113
  let recv = ffikit::initialize_ffi().unwrap();
@@ -105,13 +132,20 @@ pub extern "C" fn initialize_agent(
105
132
  .unwrap()
106
133
  .to_string();
107
134
 
135
+ let compression_string = unsafe { CStr::from_ptr(compression) }
136
+ .to_str()
137
+ .unwrap()
138
+ .to_string();
139
+
140
+ let compression = Compression::from_str(&compression_string);
141
+
108
142
  let pid = std::process::id();
109
143
 
110
144
  let rbspy_config = RbspyConfig::new(pid.try_into().unwrap())
111
145
  .sample_rate(sample_rate)
112
146
  .lock_process(false)
113
- .with_subprocesses(detect_subprocesses)
114
- .on_cpu(on_cpu)
147
+ .detect_subprocesses(detect_subprocesses)
148
+ .oncpu(oncpu)
115
149
  .report_pid(report_pid)
116
150
  .report_thread_id(report_thread_id);
117
151
 
@@ -128,6 +162,10 @@ pub extern "C" fn initialize_agent(
128
162
  agent_builder = agent_builder.auth_token(auth_token);
129
163
  }
130
164
 
165
+ if let Ok(compression) = compression {
166
+ agent_builder = agent_builder.compression(compression);
167
+ }
168
+
131
169
  let agent = agent_builder.build().unwrap();
132
170
 
133
171
  let agent_running = agent.start().unwrap();
@@ -1,3 +1,3 @@
1
1
  module Pyroscope
2
- VERSION = '0.3.2'.freeze
2
+ VERSION = '0.4.0'.freeze
3
3
  end
data/lib/pyroscope.rb CHANGED
@@ -1,10 +1,14 @@
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+
1
4
  require 'ffi'
2
5
 
3
6
  module Pyroscope
4
7
  module Rust
5
8
  extend FFI::Library
6
9
  ffi_lib File.expand_path(File.dirname(__FILE__)) + "/rbspy/rbspy.#{RbConfig::CONFIG["DLEXT"]}"
7
- attach_function :initialize_agent, [:string, :string, :string, :int, :bool, :bool, :bool, :bool, :string], :bool
10
+ attach_function :initialize_logging, [:int], :bool
11
+ attach_function :initialize_agent, [:string, :string, :string, :int, :bool, :bool, :bool, :bool, :string, :string], :bool
8
12
  attach_function :add_thread_tag, [:uint64, :string, :string], :bool
9
13
  attach_function :remove_thread_tag, [:uint64, :string, :string], :bool
10
14
  attach_function :add_global_tag, [:string, :string], :bool
@@ -18,19 +22,21 @@ module Pyroscope
18
22
  attach_function :thread_id, [], :uint64
19
23
  end
20
24
 
21
- 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
25
+ Config = Struct.new(:application_name, :app_name, :server_address, :auth_token, :log_level, :sample_rate, :detect_subprocesses, :oncpu, :report_pid, :report_thread_id, :tags, :compression) do
22
26
  def initialize(*)
27
+ super
28
+ # defaults:
23
29
  self.application_name = ''
24
30
  self.server_address = 'http://localhost:4040'
25
31
  self.auth_token = ''
26
32
  self.sample_rate = 100
27
33
  self.detect_subprocesses = false
28
- self.on_cpu = true
34
+ self.oncpu = true
29
35
  self.report_pid = false
30
36
  self.report_thread_id = false
31
- self.log_level = 'info'
37
+ self.log_level = 'error'
32
38
  self.tags = {}
33
- super
39
+ self.compression = 'gzip'
34
40
  end
35
41
  end
36
42
 
@@ -41,16 +47,39 @@ module Pyroscope
41
47
  # Pass config to the block
42
48
  yield @config
43
49
 
50
+ # Determine Logging level (kinda like an enum).
51
+ case @config.log_level
52
+ when 'trace'
53
+ @log_level = 10
54
+ when 'debug'
55
+ @log_level = 20
56
+ when 'info'
57
+ @log_level = 30
58
+ when 'warn'
59
+ @log_level = 40
60
+ when 'error'
61
+ @log_level = 50
62
+ else
63
+ @log_level = 50
64
+ end
65
+
66
+ # Initialize Logging
67
+ Rust.initialize_logging(@log_level)
68
+
69
+
70
+ # initialize Pyroscope Agent
44
71
  Rust.initialize_agent(
72
+ # these are defaults in case user-provided values are nil:
45
73
  @config.app_name || @config.application_name || "",
46
74
  @config.server_address || "",
47
75
  @config.auth_token || "",
48
76
  @config.sample_rate || 100,
49
77
  @config.detect_subprocesses || false,
50
- @config.on_cpu || false,
78
+ @config.oncpu || false,
51
79
  @config.report_pid || false,
52
80
  @config.report_thread_id || false,
53
- tags_to_string(@config.tags || {})
81
+ tags_to_string(@config.tags || {}),
82
+ @config.compression || ""
54
83
  )
55
84
  end
56
85
 
@@ -96,7 +125,7 @@ module Pyroscope
96
125
  end
97
126
  end
98
127
 
99
- def drop
128
+ def shutdown
100
129
  Rust.drop_agent
101
130
  end
102
131
  end
Binary file
Binary file
data/pyroscope.gemspec CHANGED
@@ -1,4 +1,11 @@
1
- require_relative "lib/pyroscope/version"
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ begin
5
+ require File.expand_path(File.join(File.dirname(__FILE__), "lib/pyroscope/version"))
6
+ rescue LoadError
7
+ puts "WARNING: Could not load Pyroscope::VERSION"
8
+ end
2
9
 
3
10
  Gem::Specification.new do |s|
4
11
  s.name = 'pyroscope'
@@ -9,6 +16,13 @@ Gem::Specification.new do |s|
9
16
  s.email = ['contact@pyroscope.io']
10
17
  s.homepage = 'https://pyroscope.io'
11
18
  s.license = 'Apache-2.0'
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",
25
+ }
12
26
 
13
27
  # Specify which files should be added to the gem when it is released.
14
28
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
@@ -21,7 +35,7 @@ Gem::Specification.new do |s|
21
35
 
22
36
  s.platform = Gem::Platform::RUBY
23
37
 
24
- s.required_ruby_version = ">= 2.5.9"
38
+ s.required_ruby_version = ">= 1.9.3"
25
39
 
26
40
  s.extensions = ['ext/rbspy/extconf.rb', 'ext/thread_id/extconf.rb']
27
41
 
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "pyroscope"
4
+ require "pyroscope/version"
5
+
6
+ puts Pyroscope::VERSION
7
+ puts RUBY_VERSION
8
+
9
+ Pyroscope.configure do |config|
10
+ config.application_name = "#{ENV["PYROSCOPE_RUN_ID"]}"
11
+ config.server_address = "https://ingest.pyroscope.cloud"
12
+ config.auth_token = ENV["PYROSCOPE_API_TOKEN"]
13
+ config.detect_subprocesses = ENV["PYROSCOPE_DETECT_SUBPROCESSES"] == "1"
14
+ config.oncpu = ENV["PYROSCOPE_ONCPU"] == "1"
15
+ config.log_level = "trace"
16
+ config.report_pid = true
17
+ config.report_thread_id = true
18
+ config.tags = {
19
+ :region => "us-east",
20
+ :detect_subprocesses => ENV["PYROSCOPE_DETECT_SUBPROCESSES"],
21
+ :oncpu => ENV["PYROSCOPE_ONCPU"],
22
+ :version => ENV["RUBY_VERSION"],
23
+ :arch => ENV["PYROSCOPE_ARCH"]
24
+ }
25
+ end
26
+
27
+ def work(n)
28
+ i = 0
29
+ while i < n
30
+ i += 1
31
+ end
32
+ end
33
+
34
+ def fast_function
35
+ Pyroscope.tag_wrapper({"function": "fast"}) do
36
+ work(2001002000)
37
+ end
38
+ end
39
+
40
+ def slow_function
41
+ work(8001008000)
42
+ end
43
+
44
+ child_pid = fork do
45
+ puts "This is the child process"
46
+ Pyroscope.tag_wrapper({"fork": "forked"}) do
47
+ slow_function()
48
+ end
49
+ end
50
+
51
+ puts "This is the master process."
52
+
53
+ Pyroscope.tag_wrapper({"fork": "master"}) do
54
+ fast_function()
55
+ end
56
+
57
+ puts "The PID of the child process is #{child_pid}"
58
+
59
+ Pyroscope.shutdown()
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pyroscope
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.4.0
5
5
  platform: x86_64-darwin
6
6
  authors:
7
7
  - Pyroscope Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-07-22 00:00:00.000000000 Z
11
+ date: 2022-08-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -89,10 +89,16 @@ files:
89
89
  - lib/thread_id/thread_id.bundle
90
90
  - pyroscope.gemspec
91
91
  - scripts/docker.sh
92
+ - scripts/tests/test.rb
92
93
  homepage: https://pyroscope.io
93
94
  licenses:
94
95
  - Apache-2.0
95
- metadata: {}
96
+ metadata:
97
+ homepage_uri: https://pyroscope.io
98
+ bug_tracker_uri: https://github.com/pyroscope-io/pyroscope-rs/issues
99
+ documentation_uri: https://pyroscope.io/docs/ruby/
100
+ changelog_uri: https://github.com/pyroscope-io/pyroscope-rs/tree/main/pyroscope_ffi/ruby/CHANGELOG.md
101
+ source_code_uri: https://github.com/pyroscope-io/pyroscope-rs/tree/main/pyroscope_ffi/ruby
96
102
  post_install_message:
97
103
  rdoc_options: []
98
104
  require_paths:
@@ -101,7 +107,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
101
107
  requirements:
102
108
  - - ">="
103
109
  - !ruby/object:Gem::Version
104
- version: 2.5.9
110
+ version: 1.9.3
105
111
  required_rubygems_version: !ruby/object:Gem::Requirement
106
112
  requirements:
107
113
  - - ">="