pyroscope 0.2.0 → 0.3.0

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: 1b9a85beabb3eb41ba48eff7a8d46a026f0cc37eff658cf5486d7529722f3743
4
- data.tar.gz: 0f20fbd97f3e8214d2d774917a48f05ee40e33fe6d0daa0d00d115363a91a02c
3
+ metadata.gz: d844d0ba44d32a1201923e772b917ec927b3c95f0e09a051f7d212e33a603d1c
4
+ data.tar.gz: ebf2419e55b0fb78cdb8701fce737e274215b8dcec1da30c84c3c91b1cd51643
5
5
  SHA512:
6
- metadata.gz: 047c69379887ac22426dc575fede65b220a52401c6ae1da2c67111581a1e5cb082213fb430390636a5dfacb652ef8760f75354ed1063d2533b5d6dd4c29ba095
7
- data.tar.gz: 3fd5552e8c0ab0700e4639c5a7fef16aa1bd24207c26872fdbf071be5128c1c2a89e8ad607d1564ea0fd1f416e0045cb5fe02da408a33a1314e4c934b241a753
6
+ metadata.gz: 0aa05eaa6246a501c9e41a7843b13dd91fedbb1ec553e79cad75a03760222a3f8d8b292b12a23364b84e066ea8d5114a4d49eff961d78d894de6bc74b86de723
7
+ data.tar.gz: ac00d00f2daebcfec6e2cd49665f2406e9ebc238805bef87aa69a3d6a98638aef91f02d765bc7708c605e215dda6eac2176cb18139183587ae269b747d5de2f9
data/LICENSE CHANGED
@@ -187,7 +187,7 @@
187
187
  same "printed page" as the copyright notice for easier
188
188
  identification within third-party archives.
189
189
 
190
- Copyright 2021 Pyroscope
190
+ Copyright 2022 Pyroscope
191
191
 
192
192
  Licensed under the Apache License, Version 2.0 (the "License");
193
193
  you may not use this file except in compliance with the License.
data/README.md CHANGED
@@ -1,47 +1,57 @@
1
- # Pyroscope Ruby Integration
1
+ Pyroscope Ruby Integration --Beta--
2
+ =====================================
2
3
 
3
- ### What is Pyroscope
4
- [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.
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).
5
6
 
7
+ ## Installation
8
+
9
+ 1. You need the Rust toolchain to compile the library locally. To install
10
+ Rust:
6
11
 
7
- ### How to install Pyroscope for Ruby Applications
8
- Adding Pyroscope to your Gemfile
9
12
  ```
10
- bundle add pyroscope
13
+ curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain stable -y
14
+ export PATH=$PATH:/root/.cargo/bin
11
15
  ```
12
16
 
13
- ### Basic Usage of Pyroscope
17
+ 2. Building/Insalling from Rubygems
18
+
19
+ ```
20
+ gem install pyroscope_beta
14
21
  ```
15
- require 'pyroscope'
16
22
 
17
- Pyroscope.configure do |config|
18
- config.application_name = "my.ruby.app" # replace this with some name for your application
19
- config.server_address = "http://my-pyroscope-server:4040" # replace this with the address of your pyroscope server
20
- end
23
+ 3. Building/Installing from source
24
+
25
+ Change directory to `pyroscope_ffi/ruby` and run
26
+
27
+ ```
28
+ gem build pyroscope.gemspec
29
+ gem install ./pyroscope.gemspec
21
30
  ```
22
31
 
23
- ### Adding Tags
24
- Tags allow for users to view their data at different levels of granularity depending on what "slices" make sense for their application. This can be anything from region or microservice to more dynamic tags like controller or api route.
32
+ ## Configuration
33
+
34
+ Configuration is similar to the old package except for `application_name`:
25
35
 
26
36
  ```
27
- require 'pyroscope'
37
+ require 'pyroscope_beta'
28
38
 
29
39
  Pyroscope.configure do |config|
30
- config.application_name = "my.ruby.app"
31
- config.server_address = "http://my-pyroscope-server:4040"
32
-
40
+ config.application_name = "ruby.app"
41
+ config.server_address = "http://localhost:4040"
42
+ config.detect_subprocesses = true
33
43
  config.tags = {
34
- "hostname" => ENV["HOSTNAME"],
44
+ :key => "value",
35
45
  }
36
46
  end
37
-
38
- # You can use a wrapper:
39
- Pyroscope.tag_wrapper({ "controller": "slow_controller_i_want_to_profile" }) do
40
- slow_code
41
- end
42
47
  ```
43
48
 
49
+ ## Adding tags
44
50
 
45
- ### Examples
46
- For more examples see [examples/ruby](https://github.com/pyroscope-io/pyroscope/tree/main/examples/ruby) in the main repo.
51
+ Tags passed to configure are global. To tag code locally, you can use:
47
52
 
53
+ ```
54
+ Pyroscope.tag_wrapper({"profile": "profile-1"}) do
55
+ // Tagged profile
56
+ end
57
+ ```
@@ -0,0 +1,23 @@
1
+ #!/bin/sh
2
+ set -e
3
+
4
+ # Install tooling
5
+ yum -y -q install wget gcc libffi-devel openssl-devel
6
+
7
+ # Install Rust
8
+ curl https://sh.rustup.rs -sSf | sh -s -- -y
9
+ export PATH=~/.cargo/bin:$PATH
10
+
11
+ # Build wheels
12
+ /opt/python/cp37-cp37m/bin/python setup.py bdist_wheel
13
+
14
+ # Audit wheels
15
+ for wheel in dist/*.whl; do
16
+ auditwheel repair $wheel -w dist/
17
+ rm $wheel
18
+ done
19
+
20
+ # Extract wheels
21
+ for wheel in dist/*.whl; do
22
+ /opt/python/cp37-cp37m/bin/wheel unpack $wheel -d wheelhouse
23
+ done
@@ -0,0 +1,7 @@
1
+ [build-system]
2
+ requires = [
3
+ "setuptools>=42",
4
+ "wheel",
5
+ "milksnakex>=0.1.6"
6
+ ]
7
+ build-backend = "setuptools.build_meta"
@@ -0,0 +1,22 @@
1
+ [metadata]
2
+ name = rbspy
3
+ version= 1.0.0
4
+ description = Fake wheel to generate audtiwheel libs
5
+ url = https://proscope.io
6
+ maintainer = Abid Omar
7
+ maintainer_email = contact@pyroscope.io
8
+ license = Apache 2.0
9
+ classifiers =
10
+ Intended Audience :: Developers
11
+ project_urls =
12
+ Documentation = https://proscope.io
13
+ Bug Tracker = https://proscope.io
14
+ Discussions = https://proscope.io
15
+ Changelog = https://proscope.io
16
+
17
+ [options]
18
+ packages = find:
19
+ install_requires =
20
+ milksnakex>=0.1.6
21
+ include_package_data = True
22
+ zip_safe = False
@@ -0,0 +1,46 @@
1
+ import os
2
+ import sys
3
+ from setuptools import find_packages, setup
4
+ from pathlib import Path
5
+
6
+ SCRIPT_DIR = Path(__file__).resolve().parent
7
+
8
+ os.chdir(SCRIPT_DIR)
9
+
10
+ # print script_dir
11
+ print(SCRIPT_DIR)
12
+
13
+ LIB_DIR = str(SCRIPT_DIR / "../../ext/rbspy")
14
+
15
+ def build_native(spec):
16
+ # Step 1: build the rust library
17
+ build = spec.add_external_build(
18
+ cmd=['cargo', 'build', '--release'],
19
+ path=LIB_DIR
20
+ )
21
+
22
+ def find_dylib():
23
+ cargo_target = os.environ.get('CARGO_BUILD_TARGET')
24
+ if cargo_target:
25
+ in_path = 'target/%s/release' % (cargo_target)
26
+ else:
27
+ in_path = 'target/release'
28
+ return build.find_dylib('rbspy', in_path=in_path)
29
+
30
+ # Step 2: package the compiled library
31
+ rtld_flags = ["NOW"]
32
+ if sys.platform == "darwin":
33
+ rtld_flags.append("NODELETE")
34
+
35
+ spec.add_cffi_module(module_path='rbspy._native',
36
+ dylib=find_dylib,
37
+ header_filename=lambda:
38
+ build.find_header('rbspy.h',in_path='include'),
39
+ rtld_flags=rtld_flags,
40
+ )
41
+
42
+ setup(
43
+ platforms="any",
44
+ milksnake_tasks=[build_native],
45
+ setup_requires=["milksnakex>=0.1.6"],
46
+ )
@@ -0,0 +1,23 @@
1
+ #!/bin/sh
2
+ set -e
3
+
4
+ # Install tooling
5
+ yum -y -q install wget gcc libffi-devel openssl-devel
6
+
7
+ # Install Rust
8
+ curl https://sh.rustup.rs -sSf | sh -s -- -y
9
+ export PATH=~/.cargo/bin:$PATH
10
+
11
+ # Build wheels
12
+ /opt/python/cp37-cp37m/bin/python setup.py bdist_wheel
13
+
14
+ # Audit wheels
15
+ for wheel in dist/*.whl; do
16
+ auditwheel repair $wheel -w dist/
17
+ rm $wheel
18
+ done
19
+
20
+ # Extract wheels
21
+ for wheel in dist/*.whl; do
22
+ /opt/python/cp37-cp37m/bin/wheel unpack $wheel -d wheelhouse
23
+ done
@@ -0,0 +1,7 @@
1
+ [build-system]
2
+ requires = [
3
+ "setuptools>=42",
4
+ "wheel",
5
+ "milksnakex>=0.1.6"
6
+ ]
7
+ build-backend = "setuptools.build_meta"
@@ -0,0 +1,22 @@
1
+ [metadata]
2
+ name = thread_id
3
+ version= 1.0.0
4
+ description = Fake wheel to generate audtiwheel libs
5
+ url = https://proscope.io
6
+ maintainer = Abid Omar
7
+ maintainer_email = contact@pyroscope.io
8
+ license = Apache 2.0
9
+ classifiers =
10
+ Intended Audience :: Developers
11
+ project_urls =
12
+ Documentation = https://proscope.io
13
+ Bug Tracker = https://proscope.io
14
+ Discussions = https://proscope.io
15
+ Changelog = https://proscope.io
16
+
17
+ [options]
18
+ packages = find:
19
+ install_requires =
20
+ milksnakex>=0.1.6
21
+ include_package_data = True
22
+ zip_safe = False
@@ -0,0 +1,46 @@
1
+ import os
2
+ import sys
3
+ from setuptools import find_packages, setup
4
+ from pathlib import Path
5
+
6
+ SCRIPT_DIR = Path(__file__).resolve().parent
7
+
8
+ os.chdir(SCRIPT_DIR)
9
+
10
+ # print script_dir
11
+ print(SCRIPT_DIR)
12
+
13
+ LIB_DIR = str(SCRIPT_DIR / "../../ext/thread_id")
14
+
15
+ def build_native(spec):
16
+ # Step 1: build the rust library
17
+ build = spec.add_external_build(
18
+ cmd=['cargo', 'build', '--release'],
19
+ path=LIB_DIR
20
+ )
21
+
22
+ def find_dylib():
23
+ cargo_target = os.environ.get('CARGO_BUILD_TARGET')
24
+ if cargo_target:
25
+ in_path = 'target/%s/release' % (cargo_target)
26
+ else:
27
+ in_path = 'target/release'
28
+ return build.find_dylib('thread_id', in_path=in_path)
29
+
30
+ # Step 2: package the compiled library
31
+ rtld_flags = ["NOW"]
32
+ if sys.platform == "darwin":
33
+ rtld_flags.append("NODELETE")
34
+
35
+ spec.add_cffi_module(module_path='thread_id._native',
36
+ dylib=find_dylib,
37
+ header_filename=lambda:
38
+ build.find_header('thread_id.h',in_path='include'),
39
+ rtld_flags=rtld_flags,
40
+ )
41
+
42
+ setup(
43
+ platforms="any",
44
+ milksnake_tasks=[build_native],
45
+ setup_requires=["milksnakex>=0.1.6"],
46
+ )
File without changes
@@ -0,0 +1,27 @@
1
+ [package]
2
+ name = "rbspy"
3
+ version = "0.1.0"
4
+ edition = "2021"
5
+
6
+ [lib]
7
+ name = "rbspy"
8
+ crate-type = ["cdylib"]
9
+
10
+ [dependencies]
11
+ #pyroscope = {version = "0.5.2" }
12
+ pyroscope = { path = "../../../../" }
13
+ #pyroscope_rbspy = { version = "0.2" }
14
+ pyroscope_rbspy = { path = "../../../../pyroscope_backends/pyroscope_rbspy" }
15
+
16
+ [patch.crates-io]
17
+ read-process-memory = {git = "https://github.com/omarabid/read-process-memory.git", branch = "0.1.4-fix"}
18
+ rbspy = {git="https://github.com/omarabid/rbspy.git", branch="oncpu-fix"}
19
+
20
+ [build-dependencies]
21
+ cbindgen = "0.20.0"
22
+
23
+ [profile.release]
24
+ opt-level= "z"
25
+ debug = false
26
+ lto = true
27
+ codegen-units = 1
@@ -0,0 +1,164 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "shellwords"
4
+
5
+ class RbspyRakeCargoHelper
6
+ attr_reader :gemname
7
+
8
+ def initialize(gemname=File.basename(__dir__))
9
+ @gemname = gemname
10
+ end
11
+
12
+ def self.command?(name)
13
+ exts = ENV["PATHEXT"] ? ENV["PATHEXT"].split(";") : [""]
14
+ ENV["PATH"].split(File::PATH_SEPARATOR).any? do |path|
15
+ exts.any? do |ext|
16
+ exe = File.join(path, "#{name}#{ext}")
17
+ File.executable?(exe) && !File.directory?(exe)
18
+ end
19
+ end
20
+ end
21
+
22
+ def self.rust_toolchain
23
+ # return env variable if set
24
+ target = ENV["RUST_TARGET"]
25
+ return target if target
26
+
27
+ str = `rustc --version --verbose`
28
+ info = str.lines.map {|l| l.chomp.split(/:\s+/, 2)}.drop(1).to_h
29
+ info["host"]
30
+ end
31
+
32
+ def self.cargo_target_dir
33
+ return @cargo_target_dir if defined? @cargo_target_dir
34
+
35
+ str = `cargo metadata --format-version 1 --offline --no-deps --quiet`
36
+ begin
37
+ require "json"
38
+ dir = JSON.parse(str)["target_directory"]
39
+ rescue LoadError # json is usually part of the stdlib, but just in case
40
+ /"target_directory"\s*:\s*"(?<dir>[^"]*)"/ =~ str
41
+ end
42
+ @cargo_target_dir = dir || "target"
43
+ end
44
+
45
+ def self.flags
46
+ cc_flags = Shellwords.split(RbConfig.expand(RbConfig::MAKEFILE_CONFIG["CC"].dup))
47
+
48
+ ["-C", "linker=#{cc_flags.shift}",
49
+ *cc_flags.flat_map {|a| ["-C", "link-arg=#{a}"] },
50
+ "-L", "native=#{RbConfig::CONFIG["libdir"]}",
51
+ *dld_flags,
52
+ *platform_flags,
53
+ ]
54
+ end
55
+
56
+ def self.dld_flags
57
+ Shellwords.split(RbConfig::CONFIG["DLDFLAGS"]).flat_map do |arg|
58
+ arg = arg.gsub(/\$\((\w+)\)/) do
59
+ $1 == "DEFFILE" ? nil : RbConfig::CONFIG[name]
60
+ end.strip
61
+ next [] if arg.empty?
62
+
63
+ transform_flag(arg)
64
+ end
65
+ end
66
+
67
+ def self.platform_flags
68
+ return unless RbConfig::CONFIG["target_os"] =~ /mingw/i
69
+
70
+ [*Shellwords.split(RbConfig::CONFIG["LIBRUBYARG"]).flat_map {|arg| transform_flag(arg)},
71
+ "-C", "link-arg=-Wl,--dynamicbase",
72
+ "-C", "link-arg=-Wl,--disable-auto-image-base",
73
+ "-C", "link-arg=-static-libgcc"]
74
+ end
75
+
76
+ def self.transform_flag(arg)
77
+ k, v = arg.split(/(?<=..)/, 2)
78
+ case k
79
+ when "-L"
80
+ [k, "native=#{v}"]
81
+ when "-l"
82
+ [k, v]
83
+ when "-F"
84
+ ["-l", "framework=#{v}"]
85
+ else
86
+ ["-C", "link_arg=#{k}#{v}"]
87
+ end
88
+ end
89
+
90
+ def install_dir
91
+ File.expand_path(File.join("..", "..", "lib", gemname), __dir__)
92
+ end
93
+
94
+ def rust_name
95
+ prefix = "lib" unless Gem.win_platform?
96
+ suffix = if RbConfig::CONFIG["target_os"] =~ /darwin/i
97
+ ".dylib"
98
+ elsif Gem.win_platform?
99
+ ".dll"
100
+ else
101
+ ".so"
102
+ end
103
+ "#{prefix}#{gemname}#{suffix}"
104
+ end
105
+
106
+ def ruby_name
107
+ "#{gemname}.#{RbConfig::CONFIG["DLEXT"]}"
108
+ end
109
+
110
+ end
111
+
112
+ task default: [:rbspy_install, :rbspy_clean]
113
+ task rbspy: [:rbspy_install, :rbspy_clean]
114
+
115
+ desc "set dev mode for subsequent task, run like `rake dev install`"
116
+ task :rbspy_dev do
117
+ @dev = true
118
+ end
119
+
120
+ desc "build gem native extension and copy to lib"
121
+ task rbspy_install: [:rbspy_cd, :rbspy_build] do
122
+ helper = RbspyRakeCargoHelper.new
123
+ profile_dir = @dev ? "debug" : "release"
124
+ arch_dir = RbspyRakeCargoHelper.rust_toolchain
125
+ source = File.join(RbspyRakeCargoHelper.cargo_target_dir, arch_dir, profile_dir, helper.rust_name)
126
+ dest = File.join(helper.install_dir, helper.ruby_name)
127
+ mkdir_p(helper.install_dir)
128
+ rm(dest) if File.exist?(dest)
129
+ cp(source, dest)
130
+ end
131
+
132
+ desc "build gem native extension"
133
+ task rbspy_build: [:rbspy_cargo, :rbspy_cd] do
134
+ sh "cargo", "rustc", *(["--locked", "--release"] unless @dev), "--target=#{RbspyRakeCargoHelper.rust_toolchain}", "--", *RbspyRakeCargoHelper.flags
135
+ end
136
+
137
+ desc "clean up release build artifacts"
138
+ task rbspy_clean: [:rbspy_cargo, :rbspy_cd] do
139
+ sh "cargo clean --release"
140
+ end
141
+
142
+ desc "clean up build artifacts"
143
+ task rbspy_clobber: [:rbspy_cargo, :rbspy_cd] do
144
+ sh "cargo clean"
145
+ end
146
+
147
+ desc "check for cargo"
148
+ task :rbspy_cargo do
149
+ raise <<-MSG unless RbspyRakeCargoHelper.command?("cargo")
150
+ This gem requires a Rust compiler and the `cargo' build tool to build the
151
+ gem's native extension. See https://www.rust-lang.org/tools/install for
152
+ how to install Rust. `cargo' is usually part of the Rust installation.
153
+ MSG
154
+
155
+ raise <<-MSG if Gem.win_platform? && RbspyRakeCargoHelper.rust_toolchain !~ /gnu/
156
+ Found Rust toolchain `#{RbspyRakeCargoHelper.rust_toolchain}' but the gem native
157
+ extension requires the gnu toolchain on Windows.
158
+ MSG
159
+ end
160
+
161
+ # ensure task is running in the right dir
162
+ task :rbspy_cd do
163
+ cd(__dir__) unless __dir__ == pwd
164
+ end
@@ -0,0 +1,12 @@
1
+ extern crate cbindgen;
2
+
3
+ use cbindgen::Config;
4
+
5
+ fn main() {
6
+ let bindings = {
7
+ let crate_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
8
+ let config = Config::from_file("cbindgen.toml").unwrap();
9
+ cbindgen::generate_with_config(&crate_dir, config).unwrap()
10
+ };
11
+ bindings.write_to_file("include/rbspy.h");
12
+ }
@@ -0,0 +1,22 @@
1
+ # The language to output bindings in
2
+ language = "C"
3
+ documentation_style = "C"
4
+
5
+ style = "type"
6
+
7
+ # An optional name to use as an include guard
8
+ include_guard = "RBSPY_H_"
9
+ # include a comment with the version of cbindgen used to generate the file
10
+ include_version = true
11
+
12
+ # An optional string of text to output at the beginning of the generated file
13
+ header = "/* Licensed under Apache-2.0 */"
14
+ autogen_warning = "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */"
15
+
16
+ braces = "SameLine"
17
+ tab_width = 2
18
+ line_length = 80
19
+
20
+ [parse]
21
+ # Do not parse dependent crates
22
+ parse_deps = false
@@ -0,0 +1,11 @@
1
+ require 'mkmf'
2
+ require 'rake'
3
+
4
+ create_makefile('rbspy')
5
+
6
+ app = Rake.application
7
+ app.init
8
+ app.add_import 'Rakefile'
9
+ app.load_rakefile
10
+
11
+ app['default'].invoke