Skip to content

Commit

Permalink
Merge pull request #56 from pyroscope-io/0.5.4
Browse files Browse the repository at this point in the history
0.5.4
  • Loading branch information
petethepig authored Aug 18, 2022
2 parents 66b592b + 6abac67 commit 500d4a4
Show file tree
Hide file tree
Showing 15 changed files with 155 additions and 52 deletions.
11 changes: 10 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# v0.5.4
## New Features
- Add report transfromation function which allows changing the report before
sending it to the Pyroscope Server.
- Add Gzip support.

## Bug Fixes
- Use URL Builder. ([786c89b](https://github.com/pyroscope-io/pyroscope-rs/commit/786c89bb99839c45778410012a6da60267d395df))

# v0.5.3
## New features
## New Features
- Add BackendConfig to make reporting of pid, thread_id and thread_name
optional.
- Backends can add a suffix to the "application_name"
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ log = "0.4"
names = "0.13.0"
reqwest = { version = "0.11", features = ["blocking", "rustls-tls-native-roots"]}
url = "2.2.2"
libflate = "1.2.0"
libc = "^0.2.124"

[dev-dependencies]
Expand Down
4 changes: 2 additions & 2 deletions examples/internal/pyspy-connect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ fn main() -> Result<()> {
.sample_rate(100)
.lock_process(true)
.time_limit(None)
.with_subprocesses(true)
.include_idle(false)
.detect_subprocesses(true)
.oncpu(false)
.native(false);

let agent = PyroscopeAgent::builder("http://localhost:4040", "pyspy.basic")
Expand Down
2 changes: 1 addition & 1 deletion examples/internal/rbspy-connect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ fn main() -> Result<()> {
let config = RbspyConfig::new(pid)
.sample_rate(100)
.lock_process(true)
.with_subprocesses(true);
.detect_subprocesses(true);

let agent = PyroscopeAgent::builder("http://localhost:4040", "rbspy.basic")
.tags([("Host", "Ruby")].to_vec())
Expand Down
19 changes: 16 additions & 3 deletions pyroscope_ffi/ffikit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,13 @@ static ONCE: Once = Once::new();

lazy_static! {
/// Root Sender
/// This is the sender to the main loop. It is lazily initialized inside a Mutex.
static ref SENDER: Mutex<Option<Sender<Signal>>> = Mutex::new(None);
}

/// Signal enum.
/// This enum is used to send signals to the main loop. It is used to add/remove global or thread
/// tags and to exit the main loop.
#[derive(Debug, Encode, Decode, PartialEq, Clone)]
pub enum Signal {
Kill,
Expand All @@ -52,7 +56,7 @@ pub fn initialize_ffi() -> Result<Receiver<Signal>> {

// Listen for signals on the main parent process.
let fn_sender = merge_sender.clone();
let channel_listener: JoinHandle<Result<()>> = std::thread::spawn(move || {
let _channel_listener: JoinHandle<Result<()>> = std::thread::spawn(move || {
log::trace!("Spawned FFI listener thread.");

while let Ok(signal) = receiver.recv() {
Expand Down Expand Up @@ -81,7 +85,7 @@ pub fn initialize_ffi() -> Result<Receiver<Signal>> {

// Listen for signals on local socket
let socket_sender = merge_sender.clone();
let socket_listener: JoinHandle<Result<()>> = std::thread::spawn(move || {
let _socket_listener: JoinHandle<Result<()>> = std::thread::spawn(move || {
let socket_address = format!("/tmp/PYROSCOPE-{}", get_parent_pid());

log::trace!(
Expand Down Expand Up @@ -158,7 +162,16 @@ pub fn send(signal: Signal) -> Result<()> {
conn.flush()?;
} else {
// Send signal through parent process.
SENDER.lock()?.as_ref().unwrap().send(signal)?;
if let Some(sender) = &*SENDER.lock()? {
log::trace!(
target: LOG_TAG,
"Sending signal {:?} through FFI channel",
signal
);
sender.send(signal)?;
} else {
log::error!(target: LOG_TAG, "FFI channel not initialized");
}
}

Ok(())
Expand Down
2 changes: 1 addition & 1 deletion pyroscope_ffi/python/setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = pyroscope-io
version= 0.7.2
version= 0.7.3
description = Pyroscope Python integration
long_description = file: README.md
long_description_content_type = text/markdown
Expand Down
24 changes: 19 additions & 5 deletions pyroscope_ffi/ruby/ext/rbspy/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
use ffikit::Signal;
use pyroscope::backend::{Report, StackFrame, Tag};
use pyroscope::PyroscopeAgent;
use pyroscope_rbspy::{rbspy_backend, RbspyConfig};
use std::collections::hash_map::DefaultHasher;
use std::env;
use std::ffi::CStr;
use std::hash::Hasher;
use std::os::raw::c_char;
use std::str::FromStr;

use ffikit::Signal;
use pyroscope_rbspy::{rbspy_backend, RbspyConfig};

use pyroscope::{pyroscope::Compression, PyroscopeAgent};
use pyroscope::backend::{Report, StackFrame, Tag};

pub fn transform_report(report: Report) -> Report {
let cwd = env::current_dir().unwrap();
Expand Down Expand Up @@ -104,7 +107,7 @@ pub extern "C" fn initialize_logging(logging_level: u32) -> bool {
pub extern "C" fn initialize_agent(
application_name: *const c_char, server_address: *const c_char, auth_token: *const c_char,
sample_rate: u32, detect_subprocesses: bool, oncpu: bool, report_pid: bool,
report_thread_id: bool, tags: *const c_char,
report_thread_id: bool, tags: *const c_char, compression: *const c_char
) -> bool {
// Initialize FFIKit
let recv = ffikit::initialize_ffi().unwrap();
Expand All @@ -129,6 +132,13 @@ pub extern "C" fn initialize_agent(
.unwrap()
.to_string();

let compression_string = unsafe { CStr::from_ptr(compression) }
.to_str()
.unwrap()
.to_string();

let compression = Compression::from_str(&compression_string);

let pid = std::process::id();

let rbspy_config = RbspyConfig::new(pid.try_into().unwrap())
Expand All @@ -152,6 +162,10 @@ pub extern "C" fn initialize_agent(
agent_builder = agent_builder.auth_token(auth_token);
}

if let Ok(compression) = compression {
agent_builder = agent_builder.compression(compression);
}

let agent = agent_builder.build().unwrap();

let agent_running = agent.start().unwrap();
Expand Down
14 changes: 9 additions & 5 deletions pyroscope_ffi/ruby/lib/pyroscope.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module Rust
extend FFI::Library
ffi_lib File.expand_path(File.dirname(__FILE__)) + "/rbspy/rbspy.#{RbConfig::CONFIG["DLEXT"]}"
attach_function :initialize_logging, [:int], :bool
attach_function :initialize_agent, [:string, :string, :string, :int, :bool, :bool, :bool, :bool, :string], :bool
attach_function :initialize_agent, [:string, :string, :string, :int, :bool, :bool, :bool, :bool, :string, :string], :bool
attach_function :add_thread_tag, [:uint64, :string, :string], :bool
attach_function :remove_thread_tag, [:uint64, :string, :string], :bool
attach_function :add_global_tag, [:string, :string], :bool
Expand All @@ -22,8 +22,10 @@ module Utils
attach_function :thread_id, [], :uint64
end

Config = Struct.new(:application_name, :app_name, :server_address, :auth_token, :log_level, :sample_rate, :detect_subprocesses, :oncpu, :report_pid, :report_thread_id, :tags) do
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
def initialize(*)
super
# defaults:
self.application_name = ''
self.server_address = 'http://localhost:4040'
self.auth_token = ''
Expand All @@ -34,7 +36,7 @@ def initialize(*)
self.report_thread_id = false
self.log_level = 'error'
self.tags = {}
super
self.compression = 'gzip'
end
end

Expand Down Expand Up @@ -63,10 +65,11 @@ def configure

# Initialize Logging
Rust.initialize_logging(@log_level)


# initialize Pyroscope Agent
Rust.initialize_agent(
# these are defaults in case user-provided values are nil:
@config.app_name || @config.application_name || "",
@config.server_address || "",
@config.auth_token || "",
Expand All @@ -75,7 +78,8 @@ def configure
@config.oncpu || false,
@config.report_pid || false,
@config.report_thread_id || false,
tags_to_string(@config.tags || {})
tags_to_string(@config.tags || {}),
@config.compression || ""
)
end

Expand Down
2 changes: 1 addition & 1 deletion pyroscope_ffi/ruby/lib/pyroscope/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module Pyroscope
VERSION = '0.3.2'.freeze
VERSION = '0.4.1'.freeze
end
13 changes: 1 addition & 12 deletions src/backend/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,14 @@ use std::{
use super::Report;

/// Backend Config
#[derive(Debug, Copy, Clone)]
#[derive(Debug, Copy, Clone, Default)]
pub struct BackendConfig {
pub report_thread_id: bool,
pub report_thread_name: bool,
pub report_pid: bool,
pub report_oncpu: bool,
}

impl Default for BackendConfig {
fn default() -> Self {
Self {
report_thread_id: false,
report_thread_name: false,
report_pid: false,
report_oncpu: false,
}
}
}

/// Backend Trait
pub trait Backend: Send + Debug {
/// Backend Spy Name
Expand Down
53 changes: 53 additions & 0 deletions src/pyroscope.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::{
collections::HashMap,
marker::PhantomData,
str::FromStr,
sync::{
mpsc::{self, Sender},
Arc, Condvar, Mutex,
Expand All @@ -18,6 +19,7 @@ use crate::{
};

use crate::backend::BackendImpl;
use crate::pyroscope::Compression::GZIP;

const LOG_TAG: &str = "Pyroscope::Agent";

Expand All @@ -44,6 +46,8 @@ pub struct PyroscopeConfig {
pub auth_token: Option<String>,
/// Function to apply
pub func: Option<fn(Report) -> Report>,
/// Pyroscope http request body compression
pub compression: Option<Compression>,
}

impl Default for PyroscopeConfig {
Expand All @@ -59,6 +63,7 @@ impl Default for PyroscopeConfig {
spy_name: "undefined".to_string(),
auth_token: None,
func: None,
compression: None,
}
}
}
Expand All @@ -80,6 +85,7 @@ impl PyroscopeConfig {
spy_name: String::from("undefined"), // Spy Name should be set by the backend
auth_token: None, // No authentication token
func: None, // No function
compression: None,
}
}

Expand Down Expand Up @@ -150,6 +156,22 @@ impl PyroscopeConfig {
..self
}
}


/// Set the http request body compression.
///
/// # Example
/// ```ignore
/// use pyroscope::pyroscope::PyroscopeConfig;
/// let config = PyroscopeConfig::new("http://localhost:8080", "my-app")
/// .compression(GZIP);
/// ```
pub fn compression(self, compression: Compression) -> Self {
Self {
compression: Some(compression),
..self
}
}
}

/// PyroscopeAgent Builder
Expand Down Expand Up @@ -288,6 +310,22 @@ impl PyroscopeAgentBuilder {
}
}

/// Set the http request body compression.
///
/// # Example
/// ```ignore
/// use pyroscope::pyroscope::PyroscopeConfig;
/// let agent = PyroscopeAgentBuilder::new("http://localhost:8080", "my-app")
/// .compression(GZIP)
/// .build();
/// ```
pub fn compression(self, compression: Compression) -> Self {
Self {
config: self.config.compression(compression),
..self
}
}

/// Initialize the backend, timer and return a PyroscopeAgent with Ready
/// state. While you can call this method, you should call it through the
/// `PyroscopeAgent.build()` method.
Expand Down Expand Up @@ -344,6 +382,21 @@ impl PyroscopeAgentBuilder {
}
}

#[derive(Clone, Debug)]
pub enum Compression {
GZIP
}

impl FromStr for Compression {
type Err = ();
fn from_str(input: &str) -> std::result::Result<Compression, Self::Err> {
match input {
"gzip" => Ok(GZIP),
_ => Err(()),
}
}
}

/// This trait is used to encode the state of the agent.
pub trait PyroscopeAgentState {}

Expand Down
Loading

0 comments on commit 500d4a4

Please sign in to comment.