pyroscope 0.3.2-x86_64-linux → 0.4.0-x86_64-linux

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0357ffeb818718a812ed4bf7fcf606f8a76eeb0d8b2c32921a84763ade61631b
4
- data.tar.gz: 6dea904d0841a5f87477105d2d58ea19a7357bc9eb982d165582e21302d275cd
3
+ metadata.gz: e7e0a308394bd54ce968d7649712148526d1696b363c3d6e37f8b62bf8d83ceb
4
+ data.tar.gz: 7527ddda6ca70869a9115e8264510fc09ea4880aaa3e3da749efa07bd83334da
5
5
  SHA512:
6
- metadata.gz: 8758d7332fb1b03028038af6a0718bc7a43ee1bce036d33735ac5618dc01218ab8a1faede0e2369c5be67cb845949f576d16f709d7354cbd95562bcc4d0675d8
7
- data.tar.gz: 88eb85ba14f0fd13448451d8e81e91f7ed667bd42cc32a6ec2b6e39cd31e4307e3a749cad146f159bb2c459a79f0e3463f5294bf20fc69ce757176cd3687bf85
6
+ metadata.gz: ef8491839fcb25cb469c8d44ab1a57ccfc8100fb6d08b8ba12192063dc89289e741cde042e1b66f73fc4345ec2c7418535968d8399d5f41a54b3918b26046693
7
+ data.tar.gz: 48d7c8c58f94ba89ad36728a998fc04ed49e38a4bb4809eb0d602c1a1a3f7b7168cdeb4f498cc3b84d28b4eeb9a0dd72634c3653b7417f7c0ac5281041e07db7
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
data/lib/rbspy/rbspy.so CHANGED
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-linux
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
@@ -98,10 +98,16 @@ files:
98
98
  - lib/thread_id/thread_id.so
99
99
  - pyroscope.gemspec
100
100
  - scripts/docker.sh
101
+ - scripts/tests/test.rb
101
102
  homepage: https://pyroscope.io
102
103
  licenses:
103
104
  - Apache-2.0
104
- metadata: {}
105
+ metadata:
106
+ homepage_uri: https://pyroscope.io
107
+ bug_tracker_uri: https://github.com/pyroscope-io/pyroscope-rs/issues
108
+ documentation_uri: https://pyroscope.io/docs/ruby/
109
+ changelog_uri: https://github.com/pyroscope-io/pyroscope-rs/tree/main/pyroscope_ffi/ruby/CHANGELOG.md
110
+ source_code_uri: https://github.com/pyroscope-io/pyroscope-rs/tree/main/pyroscope_ffi/ruby
105
111
  post_install_message:
106
112
  rdoc_options: []
107
113
  require_paths:
@@ -110,7 +116,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
110
116
  requirements:
111
117
  - - ">="
112
118
  - !ruby/object:Gem::Version
113
- version: 2.5.9
119
+ version: 1.9.3
114
120
  required_rubygems_version: !ruby/object:Gem::Requirement
115
121
  requirements:
116
122
  - - ">="