pyroscope 0.6.7 → 1.0.9

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.
data/ext/rbspy/src/lib.rs CHANGED
@@ -1,25 +1,26 @@
1
- use std::collections::hash_map::DefaultHasher;
1
+ mod backend;
2
+
3
+ use rbspy::sampler::Sampler;
4
+ use remoteprocess::Pid;
2
5
  use std::env;
3
6
  use std::ffi::CStr;
4
- use std::hash::Hasher;
5
7
  use std::os::raw::c_char;
6
- use std::str::FromStr;
7
-
8
- use ffikit::Signal;
9
- use pyroscope_rbspy::{rbspy_backend, RbspyConfig};
10
8
 
11
- use pyroscope;
12
- use pyroscope::{pyroscope::Compression, PyroscopeAgent};
13
- use pyroscope::backend::{Report, StackFrame, Tag};
14
- use pyroscope::pyroscope::ReportEncoding;
9
+ use crate::backend::Rbspy;
10
+ use pyroscope::backend::{BackendConfig, BackendImpl, Report, StackFrame, Tag};
11
+ use pyroscope::pyroscope::PyroscopeAgentBuilder;
15
12
 
16
13
  const LOG_TAG: &str = "Pyroscope::rbspy::ffi";
14
+ const RBSPY_NAME: &str = "rbspy";
15
+ const RBSPY_VERSION: &str = env!("CARGO_PKG_VERSION");
17
16
 
17
+ fn transform_report_with_current_dir(report: Report) -> Report {
18
+ let cwd = env::current_dir().ok();
19
+ let cwd = cwd.as_deref().and_then(|p| p.to_str());
20
+ transform_report(report, cwd)
21
+ }
18
22
 
19
- pub fn transform_report(report: Report) -> Report {
20
- let cwd = env::current_dir().unwrap();
21
- let cwd = cwd.to_str().unwrap_or("");
22
-
23
+ pub fn transform_report(report: Report, cwd: Option<&str>) -> Report {
23
24
  let data = report
24
25
  .data
25
26
  .iter()
@@ -30,27 +31,18 @@ pub fn transform_report(report: Report) -> Report {
30
31
  .map(|frame| {
31
32
  let frame = frame.to_owned();
32
33
  let mut s = frame.filename.unwrap();
33
- match s.find(cwd) {
34
- Some(i) => {
35
- s = s[(i + cwd.len() + 1)..].to_string();
34
+ let stripped = cwd
35
+ .and_then(|c| s.strip_prefix(c))
36
+ .and_then(|rest| rest.strip_prefix('/'));
37
+ if let Some(rest) = stripped {
38
+ s = rest.to_string();
39
+ } else if let Some(i) = s.find("/gems/") {
40
+ s = s[(i + 1)..].to_string();
41
+ } else if let Some(i) = s.find("/ruby/") {
42
+ s = s[(i + 6)..].to_string();
43
+ if let Some(i) = s.find('/') {
44
+ s = s[(i + 1)..].to_string();
36
45
  }
37
- None => match s.find("/gems/") {
38
- Some(i) => {
39
- s = s[(i + 1)..].to_string();
40
- }
41
- None => match s.find("/ruby/") {
42
- Some(i) => {
43
- s = s[(i + 6)..].to_string();
44
- match s.find("/") {
45
- Some(i) => {
46
- s = s[(i + 1)..].to_string();
47
- }
48
- None => {}
49
- }
50
- }
51
- None => {}
52
- },
53
- },
54
46
  }
55
47
 
56
48
  // something
@@ -73,9 +65,7 @@ pub fn transform_report(report: Report) -> Report {
73
65
  })
74
66
  .collect();
75
67
 
76
- let new_report = Report::new(data).metadata(report.metadata.clone());
77
-
78
- new_report
68
+ Report::new(data).metadata(report.metadata.clone())
79
69
  }
80
70
 
81
71
  #[no_mangle]
@@ -109,42 +99,27 @@ pub extern "C" fn initialize_logging(logging_level: u32) -> bool {
109
99
  }
110
100
 
111
101
  #[no_mangle]
112
- pub extern "C" fn initialize_agent(
102
+ /// # Safety
103
+ /// All pointer arguments must be valid, non-null, null-terminated C strings.
104
+ pub unsafe extern "C" fn initialize_agent(
113
105
  application_name: *const c_char,
114
106
  server_address: *const c_char,
115
- auth_token: *const c_char,
116
107
  basic_auth_user: *const c_char,
117
108
  basic_auth_password: *const c_char,
118
109
  sample_rate: u32,
119
- detect_subprocesses: bool,
120
110
  oncpu: bool,
121
111
  report_pid: bool,
122
112
  report_thread_id: bool,
123
113
  tags: *const c_char,
124
- compression: *const c_char,
125
- _report_encoding: *const c_char,
126
114
  tenant_id: *const c_char,
127
115
  http_headers_json: *const c_char,
128
116
  ) -> bool {
129
- // Initialize FFIKit
130
- let recv = ffikit::initialize_ffi().unwrap();
131
-
132
117
  let application_name = unsafe { CStr::from_ptr(application_name) }
133
118
  .to_str()
134
119
  .unwrap()
135
120
  .to_string();
136
121
 
137
- let mut server_address = unsafe { CStr::from_ptr(server_address) }
138
- .to_str()
139
- .unwrap()
140
- .to_string();
141
-
142
- let adhoc_server_address = std::env::var("PYROSCOPE_ADHOC_SERVER_ADDRESS");
143
- if let Ok(adhoc_server_address) = adhoc_server_address {
144
- server_address = adhoc_server_address
145
- }
146
-
147
- let auth_token = unsafe { CStr::from_ptr(auth_token) }
122
+ let server_address = unsafe { CStr::from_ptr(server_address) }
148
123
  .to_str()
149
124
  .unwrap()
150
125
  .to_string();
@@ -164,11 +139,6 @@ pub extern "C" fn initialize_agent(
164
139
  .unwrap()
165
140
  .to_string();
166
141
 
167
- let compression_string = unsafe { CStr::from_ptr(compression) }
168
- .to_str()
169
- .unwrap()
170
- .to_string();
171
-
172
142
  let tenant_id = unsafe { CStr::from_ptr(tenant_id) }
173
143
  .to_str()
174
144
  .unwrap()
@@ -179,35 +149,36 @@ pub extern "C" fn initialize_agent(
179
149
  .unwrap()
180
150
  .to_string();
181
151
 
182
- let compression = Compression::from_str(&compression_string);
183
-
184
152
  let pid = std::process::id();
185
153
 
186
- let rbspy_config = RbspyConfig::new(pid.try_into().unwrap())
187
- .sample_rate(sample_rate)
188
- .lock_process(false)
189
- .detect_subprocesses(detect_subprocesses)
190
- .oncpu(oncpu)
191
- .report_pid(report_pid)
192
- .report_thread_id(report_thread_id);
154
+ let backend_config = BackendConfig {
155
+ report_thread_id,
156
+ report_thread_name: false,
157
+ report_pid,
158
+ };
159
+
160
+ let sampler = Sampler::new(pid as Pid, sample_rate, false, None, false, None, oncpu);
193
161
 
194
162
  let tags_ref = tags_string.as_str();
195
163
  let tags = string_to_tags(tags_ref);
196
- let rbspy = rbspy_backend(rbspy_config);
197
-
198
- let mut agent_builder = PyroscopeAgent::builder(server_address, application_name)
199
- .backend(rbspy)
200
- .func(transform_report)
201
- .tags(tags)
202
- .report_encoding(ReportEncoding::PPROF);
203
-
204
- if auth_token != "" {
205
- agent_builder = agent_builder.auth_token(auth_token);
206
- } else if basic_auth_user != "" && basic_auth_password != "" {
164
+ let rbspy = BackendImpl::new(Box::new(Rbspy::new(sampler, sample_rate, backend_config)));
165
+
166
+ let mut agent_builder = PyroscopeAgentBuilder::new(
167
+ server_address,
168
+ application_name,
169
+ sample_rate,
170
+ RBSPY_NAME,
171
+ RBSPY_VERSION,
172
+ rbspy,
173
+ )
174
+ .func(transform_report_with_current_dir)
175
+ .tags(tags);
176
+
177
+ if !basic_auth_user.is_empty() && !basic_auth_password.is_empty() {
207
178
  agent_builder = agent_builder.basic_auth(basic_auth_user, basic_auth_password);
208
179
  }
209
180
 
210
- if tenant_id != "" {
181
+ if !tenant_id.is_empty() {
211
182
  agent_builder = agent_builder.tenant_id(tenant_id);
212
183
  }
213
184
 
@@ -216,131 +187,60 @@ pub extern "C" fn initialize_agent(
216
187
  Ok(http_headers) => {
217
188
  agent_builder = agent_builder.http_headers(http_headers);
218
189
  }
219
- Err(e) => {
220
- match e {
221
- pyroscope::PyroscopeError::Json(e) => {
222
- log::error!(target: LOG_TAG, "parse_http_headers_json error {}", e);
223
- }
224
- pyroscope::PyroscopeError::AdHoc(e) => {
225
- log::error!(target: LOG_TAG, "parse_http_headers_json {}", e);
226
- }
227
- _ => {}
190
+ Err(e) => match e {
191
+ pyroscope::PyroscopeError::Json(e) => {
192
+ log::error!(target: LOG_TAG, "parse_http_headers_json error {}", e);
228
193
  }
229
- }
230
- }
231
-
232
- if let Ok(compression) = compression {
233
- agent_builder = agent_builder.compression(compression);
234
- }
235
-
236
- let agent = agent_builder.build().unwrap();
237
-
238
- let agent_running = agent.start().unwrap();
239
-
240
- std::thread::spawn(move || {
241
- while let Ok(signal) = recv.recv() {
242
- match signal {
243
- Signal::Kill => {
244
- agent_running.stop().unwrap();
245
- break;
246
- }
247
- Signal::AddGlobalTag(name, value) => {
248
- agent_running.add_global_tag(Tag::new(name, value)).unwrap();
249
- }
250
- Signal::RemoveGlobalTag(name, value) => {
251
- agent_running
252
- .remove_global_tag(Tag::new(name, value))
253
- .unwrap();
254
- }
255
- Signal::AddThreadTag(thread_id, key, value) => {
256
- let tag = Tag::new(key, value);
257
- agent_running.add_thread_tag(thread_id, tag).unwrap();
258
- }
259
- Signal::RemoveThreadTag(thread_id, key, value) => {
260
- let tag = Tag::new(key, value);
261
- agent_running.remove_thread_tag(thread_id, tag).unwrap();
262
- }
194
+ pyroscope::PyroscopeError::AdHoc(e) => {
195
+ log::error!(target: LOG_TAG, "parse_http_headers_json {}", e);
263
196
  }
264
- }
265
- });
197
+ _ => {}
198
+ },
199
+ }
266
200
 
267
- true
201
+ pyroscope::ffikit::run(agent_builder).is_ok()
268
202
  }
269
203
 
270
204
  #[no_mangle]
271
205
  pub extern "C" fn drop_agent() -> bool {
272
- // Send Kill signal to the FFI merge channel.
273
- ffikit::send(ffikit::Signal::Kill).unwrap();
274
-
275
- true
276
- }
277
-
278
- #[no_mangle]
279
- pub extern "C" fn add_thread_tag(thread_id: u64, key: *const c_char, value: *const c_char) -> bool {
280
- let key = unsafe { CStr::from_ptr(key) }.to_str().unwrap().to_owned();
281
- let value = unsafe { CStr::from_ptr(value) }
282
- .to_str()
283
- .unwrap()
284
- .to_owned();
285
-
286
- let pid = std::process::id();
287
- let mut hasher = DefaultHasher::new();
288
- hasher.write_u64(thread_id % pid as u64);
289
- let id = hasher.finish();
290
-
291
- ffikit::send(ffikit::Signal::AddThreadTag(id, key, value)).unwrap();
292
-
293
- true
206
+ pyroscope::ffikit::send(pyroscope::ffikit::Signal::Kill).is_ok()
294
207
  }
295
208
 
296
209
  #[no_mangle]
297
- pub extern "C" fn remove_thread_tag(
298
- thread_id: u64, key: *const c_char, value: *const c_char,
299
- ) -> bool {
210
+ /// # Safety
211
+ /// `key` and `value` must be valid, non-null, null-terminated C strings.
212
+ pub unsafe extern "C" fn add_thread_tag(key: *const c_char, value: *const c_char) -> bool {
300
213
  let key = unsafe { CStr::from_ptr(key) }.to_str().unwrap().to_owned();
301
214
  let value = unsafe { CStr::from_ptr(value) }
302
215
  .to_str()
303
216
  .unwrap()
304
217
  .to_owned();
305
218
 
306
- let pid = std::process::id();
307
- let mut hasher = DefaultHasher::new();
308
- hasher.write_u64(thread_id % pid as u64);
309
- let id = hasher.finish();
310
-
311
- ffikit::send(ffikit::Signal::RemoveThreadTag(id, key, value)).unwrap();
312
-
313
- true
219
+ pyroscope::ffikit::send(pyroscope::ffikit::Signal::AddThreadTag(
220
+ backend::self_thread_id(),
221
+ Tag { key, value },
222
+ ))
223
+ .is_ok()
314
224
  }
315
225
 
316
226
  #[no_mangle]
317
- pub extern "C" fn add_global_tag(key: *const c_char, value: *const c_char) -> bool {
227
+ /// # Safety
228
+ /// `key` and `value` must be valid, non-null, null-terminated C strings.
229
+ pub unsafe extern "C" fn remove_thread_tag(key: *const c_char, value: *const c_char) -> bool {
318
230
  let key = unsafe { CStr::from_ptr(key) }.to_str().unwrap().to_owned();
319
231
  let value = unsafe { CStr::from_ptr(value) }
320
232
  .to_str()
321
233
  .unwrap()
322
234
  .to_owned();
323
235
 
324
- ffikit::send(ffikit::Signal::AddGlobalTag(key, value)).unwrap();
325
-
326
- true
236
+ pyroscope::ffikit::send(pyroscope::ffikit::Signal::RemoveThreadTag(
237
+ backend::self_thread_id(),
238
+ Tag { key, value },
239
+ ))
240
+ .is_ok()
327
241
  }
328
242
 
329
- #[no_mangle]
330
- pub extern "C" fn remove_global_tag(key: *const c_char, value: *const c_char) -> bool {
331
- let key = unsafe { CStr::from_ptr(key) }.to_str().unwrap().to_owned();
332
- let value = unsafe { CStr::from_ptr(value) }
333
- .to_str()
334
- .unwrap()
335
- .to_owned();
336
-
337
- ffikit::send(ffikit::Signal::RemoveGlobalTag(key, value)).unwrap();
338
-
339
- true
340
- }
341
-
342
- // Convert a string of tags to a Vec<(&str, &str)>
343
- fn string_to_tags<'a>(tags: &'a str) -> Vec<(&'a str, &'a str)> {
243
+ fn string_to_tags(tags: &str) -> Vec<(&str, &str)> {
344
244
  let mut tags_vec = Vec::new();
345
245
  // check if string is empty
346
246
  if tags.is_empty() {
@@ -356,3 +256,93 @@ fn string_to_tags<'a>(tags: &'a str) -> Vec<(&'a str, &'a str)> {
356
256
 
357
257
  tags_vec
358
258
  }
259
+
260
+ #[cfg(test)]
261
+ mod tests {
262
+ use super::*;
263
+ use pyroscope::backend::{Report, StackFrame, StackTrace};
264
+ use std::collections::HashMap;
265
+
266
+ fn report_with_filename(filename: &str) -> Report {
267
+ let stacktrace = StackTrace {
268
+ frames: vec![StackFrame {
269
+ filename: Some(filename.to_string()),
270
+ ..Default::default()
271
+ }],
272
+ ..Default::default()
273
+ };
274
+ Report::new(HashMap::from([(stacktrace, 1)]))
275
+ }
276
+
277
+ fn transformed_filename(report: Report) -> String {
278
+ let (stacktrace, _) = report.data.iter().next().unwrap();
279
+ stacktrace.frames[0].filename.clone().unwrap()
280
+ }
281
+
282
+ #[test]
283
+ fn transform_report_does_not_panic_when_cwd_is_a_suffix_of_filename() {
284
+ let report = report_with_filename("bin/rails");
285
+ let out = transform_report(report, Some("/rails"));
286
+ assert_eq!(transformed_filename(out), "bin/rails");
287
+ }
288
+
289
+ #[test]
290
+ fn transform_report_strips_cwd_prefix() {
291
+ let report = report_with_filename("/rails/app/models/user.rb");
292
+ let out = transform_report(report, Some("/rails"));
293
+ assert_eq!(transformed_filename(out), "app/models/user.rb");
294
+ }
295
+
296
+ #[test]
297
+ fn transform_report_rewrites_gems_path() {
298
+ let report =
299
+ report_with_filename("/usr/local/bundle/gems/activerecord-7.0.0/lib/active_record.rb");
300
+ let out = transform_report(report, None);
301
+ assert_eq!(
302
+ transformed_filename(out),
303
+ "gems/activerecord-7.0.0/lib/active_record.rb",
304
+ );
305
+ }
306
+
307
+ #[test]
308
+ fn transform_report_rewrites_ruby_stdlib_path() {
309
+ let report = report_with_filename("/usr/local/lib/ruby/3.3.0/json/common.rb");
310
+ let out = transform_report(report, None);
311
+ assert_eq!(transformed_filename(out), "json/common.rb");
312
+ }
313
+
314
+ #[test]
315
+ fn transform_report_leaves_unrelated_filename_unchanged() {
316
+ let report = report_with_filename("/tmp/unrelated.rb");
317
+ let out = transform_report(report, Some("/app"));
318
+ assert_eq!(transformed_filename(out), "/tmp/unrelated.rb");
319
+ }
320
+
321
+ #[test]
322
+ fn test_cargo_version_matches_ruby_version() {
323
+ let cargo_version = env!("CARGO_PKG_VERSION");
324
+ let version_rb = include_str!("../../../lib/pyroscope/version.rb");
325
+ let ruby_version = version_rb
326
+ .lines()
327
+ .find_map(|line| {
328
+ let line = line.trim();
329
+ if line.starts_with("VERSION") {
330
+ let start = line.find('\'')?;
331
+ let end = line.rfind('\'')?;
332
+ if start < end {
333
+ Some(&line[start + 1..end])
334
+ } else {
335
+ None
336
+ }
337
+ } else {
338
+ None
339
+ }
340
+ })
341
+ .expect("could not find VERSION in lib/pyroscope/version.rb");
342
+
343
+ assert_eq!(
344
+ cargo_version, ruby_version,
345
+ "Cargo.toml version ({cargo_version}) does not match lib/pyroscope/version.rb ({ruby_version})"
346
+ );
347
+ }
348
+ }
@@ -1,3 +1,3 @@
1
1
  module Pyroscope
2
- VERSION = '0.6.7'.freeze
2
+ VERSION = '1.0.9'.freeze # x-release-please-version
3
3
  end
data/lib/pyroscope.rb CHANGED
@@ -9,20 +9,12 @@ module Pyroscope
9
9
  extend FFI::Library
10
10
  ffi_lib File.expand_path(File.dirname(__FILE__)) + "/rbspy/rbspy.#{RbConfig::CONFIG["DLEXT"]}"
11
11
  attach_function :initialize_logging, [:int], :bool
12
- attach_function :initialize_agent, [:string, :string, :string, :string, :string, :int, :bool, :bool, :bool, :bool, :string, :string, :string, :string, :string], :bool
13
- attach_function :add_thread_tag, [:uint64, :string, :string], :bool
14
- attach_function :remove_thread_tag, [:uint64, :string, :string], :bool
15
- attach_function :add_global_tag, [:string, :string], :bool
16
- attach_function :remove_global_tag, [:string, :string], :bool
12
+ attach_function :initialize_agent, [:string, :string, :string, :string, :int, :bool, :bool, :bool, :string, :string, :string], :bool
13
+ attach_function :add_thread_tag, [:string, :string], :bool
14
+ attach_function :remove_thread_tag, [:string, :string], :bool
17
15
  attach_function :drop_agent, [], :bool
18
16
  end
19
17
 
20
- module Utils
21
- extend FFI::Library
22
- ffi_lib File.expand_path(File.dirname(__FILE__)) + "/thread_id/thread_id.#{RbConfig::CONFIG["DLEXT"]}"
23
- attach_function :thread_id, [], :uint64
24
- end
25
-
26
18
  if defined?(::Rails::Engine)
27
19
  class Engine < ::Rails::Engine
28
20
  config.after_initialize do
@@ -37,12 +29,10 @@ module Pyroscope
37
29
  :application_name,
38
30
  :app_name,
39
31
  :server_address,
40
- :auth_token,
41
32
  :basic_auth_username,
42
33
  :basic_auth_password,
43
34
  :log_level,
44
35
  :sample_rate,
45
- :detect_subprocesses,
46
36
  :oncpu,
47
37
  :report_pid,
48
38
  :report_thread_id,
@@ -58,11 +48,9 @@ module Pyroscope
58
48
  # defaults:
59
49
  self.application_name = ''
60
50
  self.server_address = 'http://localhost:4040'
61
- self.auth_token = ''
62
51
  self.basic_auth_username = ''
63
52
  self.basic_auth_password = ''
64
53
  self.sample_rate = 100
65
- self.detect_subprocesses = false
66
54
  self.oncpu = true
67
55
  self.report_pid = false
68
56
  self.report_thread_id = false
@@ -109,17 +97,13 @@ module Pyroscope
109
97
  # these are defaults in case user-provided values are nil:
110
98
  @config.app_name || @config.application_name || "",
111
99
  @config.server_address || "",
112
- @config.auth_token || "",
113
100
  @config.basic_auth_username || "",
114
101
  @config.basic_auth_password || "",
115
102
  @config.sample_rate || 100,
116
- @config.detect_subprocesses || false,
117
103
  @config.oncpu || false,
118
104
  @config.report_pid || false,
119
105
  @config.report_thread_id || false,
120
106
  tags_to_string(@config.tags || {}),
121
- @config.compression || "",
122
- @config.report_encoding || "pprof",
123
107
  @config.tenant_id || "",
124
108
  http_headers_to_json(@config.http_headers || {})
125
109
  )
@@ -137,12 +121,11 @@ module Pyroscope
137
121
  end
138
122
 
139
123
  def tag_wrapper(tags)
140
- tid = thread_id
141
- _add_tags(tid, tags)
124
+ _add_tags(tags)
142
125
  begin
143
126
  yield
144
127
  ensure
145
- _remove_tags(tid, tags)
128
+ _remove_tags(tags)
146
129
  end
147
130
  end
148
131
 
@@ -154,19 +137,15 @@ module Pyroscope
154
137
  warn("deprecated. Use `Pyroscope.tag_wrapper` instead.")
155
138
  end
156
139
 
157
- def thread_id
158
- return Utils.thread_id
159
- end
160
-
161
- def _add_tags(thread_id, tags)
140
+ def _add_tags(tags)
162
141
  tags.each do |tag_name, tag_value|
163
- Rust.add_thread_tag(thread_id, tag_name.to_s, tag_value.to_s)
142
+ Rust.add_thread_tag(tag_name.to_s, tag_value.to_s)
164
143
  end
165
144
  end
166
145
 
167
- def _remove_tags(thread_id, tags)
146
+ def _remove_tags(tags)
168
147
  tags.each do |tag_name, tag_value|
169
- Rust.remove_thread_tag(thread_id, tag_name.to_s, tag_value.to_s)
148
+ Rust.remove_thread_tag(tag_name.to_s, tag_value.to_s)
170
149
  end
171
150
  end
172
151
 
data/pyroscope.gemspec CHANGED
@@ -14,55 +14,37 @@ 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)/ }
35
26
  s.files = [
36
27
  "Gemfile",
37
28
  "Gemfile.lock",
38
29
  "LICENSE",
39
- # "Makefile",
40
30
  "README.md",
41
- # "Rakefile",
31
+ "ext/rbspy/Cargo.lock",
42
32
  "ext/rbspy/Cargo.toml",
43
33
  "ext/rbspy/Rakefile",
44
- "ext/rbspy/build.rs",
45
34
  "ext/rbspy/cbindgen.toml",
46
35
  "ext/rbspy/extconf.rb",
47
36
  "ext/rbspy/include/rbspy.h",
37
+ "ext/rbspy/src/backend.rs",
48
38
  "ext/rbspy/src/lib.rs",
49
- "ext/thread_id/Cargo.toml",
50
- "ext/thread_id/Rakefile",
51
- "ext/thread_id/build.rs",
52
- "ext/thread_id/cbindgen.toml",
53
- "ext/thread_id/extconf.rb",
54
- "ext/thread_id/include/thread_id.h",
55
- "ext/thread_id/src/lib.rs",
56
39
  "lib/pyroscope.rb",
57
40
  "lib/pyroscope/version.rb",
58
41
  "pyroscope.gemspec",
59
- # "scripts/tests/test.rb",
60
42
  ]
61
43
  s.platform = Gem::Platform::RUBY
62
44
 
63
45
  s.required_ruby_version = ">= 1.9.3"
64
46
 
65
- s.extensions = ['ext/rbspy/extconf.rb', 'ext/thread_id/extconf.rb']
47
+ s.extensions = ['ext/rbspy/extconf.rb']
66
48
 
67
49
  s.add_dependency 'ffi'
68
50