pyroscope 1.0.9-aarch64-linux → 1.1.0-aarch64-linux
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 +1 -1
- data/ext/rbspy/Cargo.lock +201 -292
- data/ext/rbspy/Cargo.toml +10 -3
- data/ext/rbspy/include/rbspy.h +2 -0
- data/ext/rbspy/src/backend/backend.rs +134 -0
- data/ext/rbspy/src/backend/mod.rs +8 -0
- data/ext/rbspy/src/backend/ruleset.rs +82 -0
- data/ext/rbspy/src/backend/tests.rs +378 -0
- data/ext/rbspy/src/backend/types.rs +303 -0
- data/ext/rbspy/src/encode/gen/google.rs +233 -0
- data/ext/rbspy/src/encode/gen/mod.rs +3 -0
- data/ext/rbspy/src/encode/gen/push.rs +31 -0
- data/ext/rbspy/src/encode/gen/types.rs +11 -0
- data/ext/rbspy/src/encode/mod.rs +2 -0
- data/ext/rbspy/src/encode/pprof.rs +159 -0
- data/ext/rbspy/src/error.rs +67 -0
- data/ext/rbspy/src/ffikit.rs +76 -0
- data/ext/rbspy/src/lib.rs +41 -15
- data/ext/rbspy/src/pyroscope.rs +726 -0
- data/ext/rbspy/src/{backend.rs → rbspy_backend.rs} +3 -3
- data/ext/rbspy/src/session.rs +275 -0
- data/ext/rbspy/src/timer/epoll.rs +268 -0
- data/ext/rbspy/src/timer/kqueue.rs +191 -0
- data/ext/rbspy/src/timer/mod.rs +38 -0
- data/ext/rbspy/src/timer/sleep.rs +114 -0
- data/ext/rbspy/src/utils.rs +141 -0
- data/lib/pyroscope/version.rb +1 -1
- data/lib/pyroscope.rb +11 -1
- data/lib/rbspy/rbspy.so +0 -0
- data/pyroscope.gemspec +1 -3
- metadata +22 -2
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
use super::TimerSignal;
|
|
2
|
+
use crate::{
|
|
3
|
+
utils::{check_err, get_time_range},
|
|
4
|
+
Result,
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
use std::sync::{
|
|
8
|
+
mpsc::{channel, Receiver, Sender},
|
|
9
|
+
Arc, Mutex,
|
|
10
|
+
};
|
|
11
|
+
use std::{
|
|
12
|
+
thread::{self, JoinHandle},
|
|
13
|
+
time::Duration,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const LOG_TAG: &str = "Pyroscope::Timer";
|
|
17
|
+
|
|
18
|
+
/// A thread that sends a notification every 10th second
|
|
19
|
+
///
|
|
20
|
+
/// Timer will send an event to attached listeners (mpsc::Sender) every 10th
|
|
21
|
+
/// second (...10, ...20, ...)
|
|
22
|
+
///
|
|
23
|
+
/// The Timer thread will run continously until all Senders are dropped.
|
|
24
|
+
/// The Timer thread will be joined when all Senders are dropped.
|
|
25
|
+
|
|
26
|
+
#[derive(Debug, Default)]
|
|
27
|
+
pub struct Timer {
|
|
28
|
+
/// A vector to store listeners (mpsc::Sender)
|
|
29
|
+
txs: Arc<Mutex<Vec<Sender<TimerSignal>>>>,
|
|
30
|
+
|
|
31
|
+
/// Thread handle
|
|
32
|
+
pub handle: Option<JoinHandle<Result<()>>>,
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
impl Timer {
|
|
36
|
+
/// Initialize Timer and run a thread to send events to attached listeners
|
|
37
|
+
pub fn initialize(cycle: Duration) -> Result<Self> {
|
|
38
|
+
log::info!(target: LOG_TAG, "Initializing Timer");
|
|
39
|
+
|
|
40
|
+
let txs = Arc::new(Mutex::new(Vec::new()));
|
|
41
|
+
|
|
42
|
+
// Add Default tx
|
|
43
|
+
let (tx, _rx): (Sender<TimerSignal>, Receiver<TimerSignal>) = channel();
|
|
44
|
+
txs.lock()?.push(tx);
|
|
45
|
+
|
|
46
|
+
let kqueue = kqueue()?;
|
|
47
|
+
|
|
48
|
+
let handle = Some({
|
|
49
|
+
let txs = txs.clone();
|
|
50
|
+
thread::spawn(move || {
|
|
51
|
+
// Wait for initial expiration
|
|
52
|
+
let initial_event = Timer::register_initial_expiration(kqueue)?;
|
|
53
|
+
Timer::wait_event(kqueue, [initial_event].as_mut_ptr())?;
|
|
54
|
+
|
|
55
|
+
// Register loop event
|
|
56
|
+
let loop_event = Timer::register_loop_expiration(kqueue, cycle)?;
|
|
57
|
+
|
|
58
|
+
// Loop 10s
|
|
59
|
+
loop {
|
|
60
|
+
// Exit thread if there are no listeners
|
|
61
|
+
if txs.lock()?.is_empty() {
|
|
62
|
+
// TODO: should close file descriptors?
|
|
63
|
+
log::info!(target: LOG_TAG, "Timer thread terminated");
|
|
64
|
+
return Ok(());
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Get current time
|
|
68
|
+
let from = TimerSignal::NextSnapshot(get_time_range(0)?.from);
|
|
69
|
+
|
|
70
|
+
// Iterate through Senders
|
|
71
|
+
txs.lock()?.iter().for_each(|tx| {
|
|
72
|
+
// Send event to attached Sender
|
|
73
|
+
match tx.send(from) {
|
|
74
|
+
Ok(_) => {
|
|
75
|
+
log::trace!(target: LOG_TAG, "Sent event to listener @ {:?}", &tx)
|
|
76
|
+
}
|
|
77
|
+
Err(_e) => {} // There could be a less confusing message, or this
|
|
78
|
+
// refactored to avoid a first sender
|
|
79
|
+
//log::warn!(
|
|
80
|
+
//target: LOG_TAG,
|
|
81
|
+
//"Failed to send event to listener @ {:?} - {}",
|
|
82
|
+
//&tx,
|
|
83
|
+
//e
|
|
84
|
+
//),
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// Wait 10s
|
|
89
|
+
Timer::wait_event(kqueue, [loop_event].as_mut_ptr())?;
|
|
90
|
+
}
|
|
91
|
+
})
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
Ok(Self { handle, txs })
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/// Attach an mpsc::Sender to Timer
|
|
98
|
+
///
|
|
99
|
+
/// Timer will dispatch an event with the timestamp of the current instant,
|
|
100
|
+
/// every 10th second to all attached senders
|
|
101
|
+
pub fn attach_listener(&mut self, tx: Sender<TimerSignal>) -> Result<()> {
|
|
102
|
+
// Push Sender to a Vector of Sender(s)
|
|
103
|
+
let txs = Arc::clone(&self.txs);
|
|
104
|
+
txs.lock()?.push(tx);
|
|
105
|
+
|
|
106
|
+
Ok(())
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/// Clear the listeners (txs) from Timer. This will shutdown the Timer thread
|
|
110
|
+
pub fn drop_listeners(&mut self) -> Result<()> {
|
|
111
|
+
let txs = Arc::clone(&self.txs);
|
|
112
|
+
txs.lock()?.clear();
|
|
113
|
+
|
|
114
|
+
Ok(())
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/// Wait for the timer event
|
|
118
|
+
fn wait_event(kqueue: i32, events: *mut libc::kevent) -> Result<()> {
|
|
119
|
+
kevent(kqueue, [].as_mut_ptr(), 0, events, 1, std::ptr::null())?;
|
|
120
|
+
Ok(())
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/// Register an initial expiration event
|
|
124
|
+
fn register_initial_expiration(kqueue: i32) -> Result<libc::kevent> {
|
|
125
|
+
// Get first event time
|
|
126
|
+
let first_fire = get_time_range(0)?.until;
|
|
127
|
+
|
|
128
|
+
let initial_event = libc::kevent {
|
|
129
|
+
ident: 1,
|
|
130
|
+
filter: libc::EVFILT_TIMER,
|
|
131
|
+
flags: libc::EV_ADD | libc::EV_ENABLE | libc::EV_ONESHOT,
|
|
132
|
+
fflags: libc::NOTE_ABSOLUTE | libc::NOTE_SECONDS,
|
|
133
|
+
data: first_fire as isize,
|
|
134
|
+
udata: std::ptr::null_mut::<libc::c_void>(),
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
// add first event
|
|
138
|
+
kevent(
|
|
139
|
+
kqueue,
|
|
140
|
+
[initial_event].as_ptr(),
|
|
141
|
+
1,
|
|
142
|
+
[].as_mut_ptr(),
|
|
143
|
+
0,
|
|
144
|
+
std::ptr::null(),
|
|
145
|
+
)?;
|
|
146
|
+
|
|
147
|
+
Ok(initial_event)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/// Register a loop expiration event
|
|
151
|
+
fn register_loop_expiration(kqueue: i32, duration: Duration) -> Result<libc::kevent> {
|
|
152
|
+
let loop_event = libc::kevent {
|
|
153
|
+
ident: 1,
|
|
154
|
+
filter: libc::EVFILT_TIMER,
|
|
155
|
+
flags: libc::EV_ADD | libc::EV_ENABLE,
|
|
156
|
+
fflags: 0,
|
|
157
|
+
data: duration.as_millis() as isize,
|
|
158
|
+
udata: std::ptr::null_mut::<libc::c_void>(),
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
// add loop event
|
|
162
|
+
kevent(
|
|
163
|
+
kqueue,
|
|
164
|
+
[loop_event].as_ptr(),
|
|
165
|
+
1,
|
|
166
|
+
[].as_mut_ptr(),
|
|
167
|
+
0,
|
|
168
|
+
std::ptr::null(),
|
|
169
|
+
)?;
|
|
170
|
+
|
|
171
|
+
Ok(loop_event)
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/// libc::kqueue wrapper
|
|
176
|
+
fn kqueue() -> Result<i32> {
|
|
177
|
+
check_err(unsafe { libc::kqueue() })
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/// libc::kevent wrapper
|
|
181
|
+
fn kevent(
|
|
182
|
+
kqueue: i32,
|
|
183
|
+
change: *const libc::kevent,
|
|
184
|
+
c_count: libc::c_int,
|
|
185
|
+
events: *mut libc::kevent,
|
|
186
|
+
e_count: libc::c_int,
|
|
187
|
+
timeout: *const libc::timespec,
|
|
188
|
+
) -> Result<()> {
|
|
189
|
+
check_err(unsafe { libc::kevent(kqueue, change, c_count, events, e_count, timeout) })?;
|
|
190
|
+
Ok(())
|
|
191
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/// A signal sent to the timer.
|
|
2
|
+
///
|
|
3
|
+
/// Either schedules another wake-up, or asks
|
|
4
|
+
/// the timer thread to terminate.
|
|
5
|
+
#[derive(Debug, Clone, Copy)]
|
|
6
|
+
pub enum TimerSignal {
|
|
7
|
+
// Thread termination was requested.
|
|
8
|
+
Terminate,
|
|
9
|
+
// When to take the next snapshot using the `Backend`.
|
|
10
|
+
NextSnapshot(u64),
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
impl std::fmt::Display for TimerSignal {
|
|
14
|
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
15
|
+
match self {
|
|
16
|
+
Self::Terminate => write!(f, "Terminate"),
|
|
17
|
+
Self::NextSnapshot(when) => write!(f, "NextSnapshot({when})"),
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Possibly: ios, netbsd, openbsd, freebsd
|
|
23
|
+
#[cfg(target_os = "macos")]
|
|
24
|
+
pub mod kqueue;
|
|
25
|
+
|
|
26
|
+
#[cfg(target_os = "macos")]
|
|
27
|
+
pub use kqueue::Timer;
|
|
28
|
+
|
|
29
|
+
// Possibly: android
|
|
30
|
+
#[cfg(target_os = "linux")]
|
|
31
|
+
pub mod epoll;
|
|
32
|
+
#[cfg(target_os = "linux")]
|
|
33
|
+
pub use epoll::Timer;
|
|
34
|
+
|
|
35
|
+
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
|
|
36
|
+
pub mod sleep;
|
|
37
|
+
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
|
|
38
|
+
pub use sleep::Timer;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
use super::TimerSignal;
|
|
2
|
+
use crate::{utils::get_time_range, Result};
|
|
3
|
+
|
|
4
|
+
use std::{
|
|
5
|
+
sync::{
|
|
6
|
+
mpsc::{channel, Receiver, Sender},
|
|
7
|
+
Arc, Mutex,
|
|
8
|
+
},
|
|
9
|
+
thread::{self, JoinHandle},
|
|
10
|
+
time::Duration,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const LOG_TAG: &str = "Pyroscope::Timer";
|
|
14
|
+
|
|
15
|
+
/// A thread that sends a notification every 10th second
|
|
16
|
+
///
|
|
17
|
+
/// Timer will send an event to attached listeners (mpsc::Sender) every 10th
|
|
18
|
+
/// second (...10, ...20, ...)
|
|
19
|
+
///
|
|
20
|
+
/// The Timer thread will run continously until all Senders are dropped.
|
|
21
|
+
/// The Timer thread will be joined when all Senders are dropped.
|
|
22
|
+
|
|
23
|
+
#[derive(Debug, Default)]
|
|
24
|
+
pub struct Timer {
|
|
25
|
+
/// A vector to store listeners (mpsc::Sender)
|
|
26
|
+
txs: Arc<Mutex<Vec<Sender<TimerSignal>>>>,
|
|
27
|
+
|
|
28
|
+
/// Thread handle
|
|
29
|
+
pub handle: Option<JoinHandle<Result<()>>>,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
impl Timer {
|
|
33
|
+
/// Initialize Timer and run a thread to send events to attached listeners
|
|
34
|
+
pub fn initialize(cycle: Duration) -> Result<Self> {
|
|
35
|
+
log::info!(target: LOG_TAG, "Initializing Timer");
|
|
36
|
+
|
|
37
|
+
let txs = Arc::new(Mutex::new(Vec::new()));
|
|
38
|
+
|
|
39
|
+
// Add Default tx
|
|
40
|
+
let (tx, _rx): (Sender<TimerSignal>, Receiver<TimerSignal>) = channel();
|
|
41
|
+
txs.lock()?.push(tx);
|
|
42
|
+
|
|
43
|
+
// Spawn a Thread
|
|
44
|
+
let handle = Some({
|
|
45
|
+
let txs = txs.clone();
|
|
46
|
+
|
|
47
|
+
thread::spawn(move || {
|
|
48
|
+
// Get remaining time for 10th second fire event
|
|
49
|
+
let rem = get_time_range(0)?.rem;
|
|
50
|
+
|
|
51
|
+
// Sleep for rem seconds
|
|
52
|
+
thread::sleep(Duration::from_secs(rem));
|
|
53
|
+
|
|
54
|
+
loop {
|
|
55
|
+
// Exit thread if there are no listeners
|
|
56
|
+
if txs.lock()?.len() == 0 {
|
|
57
|
+
log::info!(target: LOG_TAG, "Timer thread terminated");
|
|
58
|
+
|
|
59
|
+
return Ok(());
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Get current time
|
|
63
|
+
let from = TimerSignal::NextSnapshot(get_time_range(0)?.from);
|
|
64
|
+
|
|
65
|
+
log::trace!(target: LOG_TAG, "Timer fired @ {}", from);
|
|
66
|
+
|
|
67
|
+
// Iterate through Senders
|
|
68
|
+
txs.lock()?.iter().for_each(|tx| {
|
|
69
|
+
// Send event to attached Sender
|
|
70
|
+
// Send event to attached Sender
|
|
71
|
+
match tx.send(from) {
|
|
72
|
+
Ok(_) => {
|
|
73
|
+
log::trace!(target: LOG_TAG, "Sent event to listener @ {:?}", &tx)
|
|
74
|
+
}
|
|
75
|
+
Err(_e) => {} // There could be a less confusing message, or this
|
|
76
|
+
// refactored to avoid a first sender
|
|
77
|
+
//log::warn!(
|
|
78
|
+
//target: LOG_TAG,
|
|
79
|
+
//"Failed to send event to listener @ {:?} - {}",
|
|
80
|
+
//&tx,
|
|
81
|
+
//e
|
|
82
|
+
//),
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Sleep for 10s
|
|
87
|
+
thread::sleep(cycle);
|
|
88
|
+
}
|
|
89
|
+
})
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
Ok(Self { handle, txs })
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/// Attach an mpsc::Sender to Timer
|
|
96
|
+
///
|
|
97
|
+
/// Timer will dispatch an event with the timestamp of the current instant,
|
|
98
|
+
/// every 10th second to all attached senders
|
|
99
|
+
pub fn attach_listener(&mut self, tx: Sender<TimerSignal>) -> Result<()> {
|
|
100
|
+
// Push Sender to a Vector of Sender(s)
|
|
101
|
+
let txs = Arc::clone(&self.txs);
|
|
102
|
+
txs.lock()?.push(tx);
|
|
103
|
+
|
|
104
|
+
Ok(())
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/// Clear the listeners (txs) from Timer. This will shutdown the Timer thread
|
|
108
|
+
pub fn drop_listeners(&mut self) -> Result<()> {
|
|
109
|
+
let txs = Arc::clone(&self.txs);
|
|
110
|
+
txs.lock()?.clear();
|
|
111
|
+
|
|
112
|
+
Ok(())
|
|
113
|
+
}
|
|
114
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
use std::fmt;
|
|
2
|
+
|
|
3
|
+
use crate::{error::Result, PyroscopeError};
|
|
4
|
+
|
|
5
|
+
/// Error Wrapper for libc return. Only check for errors.
|
|
6
|
+
pub fn check_err<T: Ord + Default>(num: T) -> Result<T> {
|
|
7
|
+
if num < T::default() {
|
|
8
|
+
return Err(PyroscopeError::from(std::io::Error::last_os_error()));
|
|
9
|
+
}
|
|
10
|
+
Ok(num)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
#[cfg(test)]
|
|
14
|
+
mod check_err_tests {
|
|
15
|
+
use crate::utils::check_err;
|
|
16
|
+
|
|
17
|
+
#[test]
|
|
18
|
+
fn check_err_success() {
|
|
19
|
+
assert_eq!(check_err(1).unwrap(), 1)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
#[test]
|
|
23
|
+
fn check_err_error() {
|
|
24
|
+
assert!(check_err(-1).is_err())
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
#[derive(Debug, Eq, PartialEq, Hash, Clone)]
|
|
29
|
+
pub struct ThreadId {
|
|
30
|
+
pthread: libc::pthread_t,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// SAFETY: pthread_t is an opaque thread identifier used as a handle,
|
|
34
|
+
// never dereferenced. On musl it's *mut c_void, on glibc it's c_ulong.
|
|
35
|
+
unsafe impl Send for ThreadId {}
|
|
36
|
+
unsafe impl Sync for ThreadId {}
|
|
37
|
+
|
|
38
|
+
impl From<libc::pthread_t> for ThreadId {
|
|
39
|
+
fn from(value: libc::pthread_t) -> Self {
|
|
40
|
+
Self { pthread: value }
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
impl ThreadId {
|
|
44
|
+
pub fn pthread_self() -> Self {
|
|
45
|
+
Self {
|
|
46
|
+
pthread: unsafe { libc::pthread_self() },
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
impl fmt::Display for ThreadId {
|
|
52
|
+
#[cfg(target_env = "musl")]
|
|
53
|
+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
54
|
+
write!(f, "{}", { self.pthread as libc::uintptr_t })
|
|
55
|
+
}
|
|
56
|
+
#[cfg(not(target_env = "musl"))]
|
|
57
|
+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
58
|
+
write!(f, "{}", { self.pthread })
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/// Return the current time in seconds.
|
|
63
|
+
pub fn get_current_time_secs() -> Result<u64> {
|
|
64
|
+
Ok(std::time::SystemTime::now()
|
|
65
|
+
.duration_since(std::time::UNIX_EPOCH)?
|
|
66
|
+
.as_secs())
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
#[cfg(test)]
|
|
70
|
+
mod get_current_time_secs_tests {
|
|
71
|
+
use crate::utils::get_current_time_secs;
|
|
72
|
+
|
|
73
|
+
#[test]
|
|
74
|
+
fn get_current_time_secs_success() {
|
|
75
|
+
assert!(get_current_time_secs().is_ok())
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/// A representation of a time range. The time range is represented by a start
|
|
80
|
+
/// time, an end time, a current time and remaining time in seconds. The
|
|
81
|
+
/// remaining time is the duration in seconds until the end time.
|
|
82
|
+
#[derive(Debug, PartialEq)]
|
|
83
|
+
pub struct TimeRange {
|
|
84
|
+
pub from: u64,
|
|
85
|
+
pub until: u64,
|
|
86
|
+
pub current: u64,
|
|
87
|
+
pub rem: u64,
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/// Return a range of timestamps in the form [start, end).
|
|
91
|
+
/// The range is inclusive of start and exclusive of end.
|
|
92
|
+
pub fn get_time_range(timestamp: u64) -> Result<TimeRange> {
|
|
93
|
+
// if timestamp is 0, then get the current time
|
|
94
|
+
if timestamp == 0 {
|
|
95
|
+
return get_time_range(get_current_time_secs()?);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Determine the start and end of the range
|
|
99
|
+
Ok(TimeRange {
|
|
100
|
+
from: timestamp / 10 * 10,
|
|
101
|
+
until: timestamp / 10 * 10 + 10,
|
|
102
|
+
current: timestamp,
|
|
103
|
+
rem: 10 - (timestamp % 10),
|
|
104
|
+
})
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
#[cfg(test)]
|
|
108
|
+
mod get_time_range_tests {
|
|
109
|
+
use crate::utils::{get_time_range, TimeRange};
|
|
110
|
+
|
|
111
|
+
#[test]
|
|
112
|
+
fn get_time_range_verify() {
|
|
113
|
+
assert_eq!(
|
|
114
|
+
get_time_range(1644194479).unwrap(),
|
|
115
|
+
TimeRange {
|
|
116
|
+
from: 1644194470,
|
|
117
|
+
until: 1644194480,
|
|
118
|
+
current: 1644194479,
|
|
119
|
+
rem: 1,
|
|
120
|
+
}
|
|
121
|
+
);
|
|
122
|
+
assert_eq!(
|
|
123
|
+
get_time_range(1644194470).unwrap(),
|
|
124
|
+
TimeRange {
|
|
125
|
+
from: 1644194470,
|
|
126
|
+
until: 1644194480,
|
|
127
|
+
current: 1644194470,
|
|
128
|
+
rem: 10,
|
|
129
|
+
}
|
|
130
|
+
);
|
|
131
|
+
assert_eq!(
|
|
132
|
+
get_time_range(1644194476).unwrap(),
|
|
133
|
+
TimeRange {
|
|
134
|
+
from: 1644194470,
|
|
135
|
+
until: 1644194480,
|
|
136
|
+
current: 1644194476,
|
|
137
|
+
rem: 4,
|
|
138
|
+
}
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
}
|
data/lib/pyroscope/version.rb
CHANGED
data/lib/pyroscope.rb
CHANGED
|
@@ -9,7 +9,7 @@ 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, :int, :bool, :bool, :bool, :string, :string, :string], :bool
|
|
12
|
+
attach_function :initialize_agent, [:string, :string, :string, :string, :int, :bool, :bool, :bool, :string, :string, :string, :string, :string], :bool
|
|
13
13
|
attach_function :add_thread_tag, [:string, :string], :bool
|
|
14
14
|
attach_function :remove_thread_tag, [:string, :string], :bool
|
|
15
15
|
attach_function :drop_agent, [], :bool
|
|
@@ -103,6 +103,8 @@ module Pyroscope
|
|
|
103
103
|
@config.oncpu || false,
|
|
104
104
|
@config.report_pid || false,
|
|
105
105
|
@config.report_thread_id || false,
|
|
106
|
+
runtime_name,
|
|
107
|
+
runtime_version,
|
|
106
108
|
tags_to_string(@config.tags || {}),
|
|
107
109
|
@config.tenant_id || "",
|
|
108
110
|
http_headers_to_json(@config.http_headers || {})
|
|
@@ -159,6 +161,14 @@ module Pyroscope
|
|
|
159
161
|
|
|
160
162
|
private
|
|
161
163
|
|
|
164
|
+
def runtime_name
|
|
165
|
+
defined?(RUBY_ENGINE) ? RUBY_ENGINE : "ruby"
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def runtime_version
|
|
169
|
+
defined?(RUBY_ENGINE_VERSION) ? RUBY_ENGINE_VERSION : RUBY_VERSION
|
|
170
|
+
end
|
|
171
|
+
|
|
162
172
|
def tags_to_string(tags)
|
|
163
173
|
tags.map { |k, v| "#{k}=#{v}" }.join(',')
|
|
164
174
|
end
|
data/lib/rbspy/rbspy.so
CHANGED
|
Binary file
|
data/pyroscope.gemspec
CHANGED
|
@@ -34,12 +34,10 @@ Gem::Specification.new do |s|
|
|
|
34
34
|
"ext/rbspy/cbindgen.toml",
|
|
35
35
|
"ext/rbspy/extconf.rb",
|
|
36
36
|
"ext/rbspy/include/rbspy.h",
|
|
37
|
-
"ext/rbspy/src/backend.rs",
|
|
38
|
-
"ext/rbspy/src/lib.rs",
|
|
39
37
|
"lib/pyroscope.rb",
|
|
40
38
|
"lib/pyroscope/version.rb",
|
|
41
39
|
"pyroscope.gemspec",
|
|
42
|
-
]
|
|
40
|
+
] + Dir["ext/rbspy/src/**/*.rs"].sort
|
|
43
41
|
s.platform = Gem::Platform::RUBY
|
|
44
42
|
|
|
45
43
|
s.required_ruby_version = ">= 1.9.3"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: pyroscope
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0
|
|
4
|
+
version: 1.1.0
|
|
5
5
|
platform: aarch64-linux
|
|
6
6
|
authors:
|
|
7
7
|
- Pyroscope Team
|
|
@@ -68,8 +68,28 @@ files:
|
|
|
68
68
|
- ext/rbspy/cbindgen.toml
|
|
69
69
|
- ext/rbspy/extconf.rb
|
|
70
70
|
- ext/rbspy/include/rbspy.h
|
|
71
|
-
- ext/rbspy/src/backend.rs
|
|
71
|
+
- ext/rbspy/src/backend/backend.rs
|
|
72
|
+
- ext/rbspy/src/backend/mod.rs
|
|
73
|
+
- ext/rbspy/src/backend/ruleset.rs
|
|
74
|
+
- ext/rbspy/src/backend/tests.rs
|
|
75
|
+
- ext/rbspy/src/backend/types.rs
|
|
76
|
+
- ext/rbspy/src/encode/gen/google.rs
|
|
77
|
+
- ext/rbspy/src/encode/gen/mod.rs
|
|
78
|
+
- ext/rbspy/src/encode/gen/push.rs
|
|
79
|
+
- ext/rbspy/src/encode/gen/types.rs
|
|
80
|
+
- ext/rbspy/src/encode/mod.rs
|
|
81
|
+
- ext/rbspy/src/encode/pprof.rs
|
|
82
|
+
- ext/rbspy/src/error.rs
|
|
83
|
+
- ext/rbspy/src/ffikit.rs
|
|
72
84
|
- ext/rbspy/src/lib.rs
|
|
85
|
+
- ext/rbspy/src/pyroscope.rs
|
|
86
|
+
- ext/rbspy/src/rbspy_backend.rs
|
|
87
|
+
- ext/rbspy/src/session.rs
|
|
88
|
+
- ext/rbspy/src/timer/epoll.rs
|
|
89
|
+
- ext/rbspy/src/timer/kqueue.rs
|
|
90
|
+
- ext/rbspy/src/timer/mod.rs
|
|
91
|
+
- ext/rbspy/src/timer/sleep.rs
|
|
92
|
+
- ext/rbspy/src/utils.rs
|
|
73
93
|
- lib/pyroscope.rb
|
|
74
94
|
- lib/pyroscope/version.rb
|
|
75
95
|
- lib/rbspy/rbspy.so
|