From 66b592b83ca245ed041c2160fada4595fcdf4a4d Mon Sep 17 00:00:00 2001 From: Abid Omar Date: Sat, 6 Aug 2022 00:37:20 +0100 Subject: [PATCH] Tests actions (#53) * imp(regex): initial regex implementation * imp(ruby): add regex support * imp(lib): add report transformation function * imp(ruby): add report transformation function * chore(release): ruby gem 0.3.2 * ruby substitute function changes * refactor(examples): change regex example * imp(lib): add iter function to Report and StackTrace * refactor(session): minor refactoring * docs(README): update README files * imp(python): add enable_logging option * imp(ruby): add logging support * refactor(ruby): update ruby spec * chore(actions): renamed ruby/python ci files * wip: update action path * wip: test download artifact * wip: fix * wip: fix * wip: fix * wip: use env * wip: use github.workspace * wip: pip install * wip: sdist job * wip: cd into directory * wip: wrong place * wip: python test files * wip: add python script runner * wip: add run_id * wip: add other scripts * wip: arm tests * wip: add setup_python * wip: add macos tests * wip: install pip for arm * wip: add setup_python for macos * wip: use apt-get instead * wip: update pip * wip: minor * chore(cli): update dependencies * imp(pyspy): harmonize API * imp: harmonize API and bump versions * imp(cli): add auth_token/oncpu options * imp(cli): auth_token implementation * wip: single test file * wip: update ffi * wip: add env variables * wip: use an integer * wip: python bool * wip: python version matrix * wip: try pip3 * wip: yaml formatting * wip: use matrix for macos tests * wip: trying something * wip: get python version details * wip: change macos version * wip: remove test scripts * wip: ruby test file * wip: initial ruby job * wip: minor updates * wip: fix script bool * wip: change test name * wip: update ruby matrix * wip: ruby macos matrix * wip: typo * wip: change macos version * wip: fix typo Co-authored-by: Dmitry Filimonov --- .github/workflows/ci-ffi-python.yml | 219 +++++++++ .github/workflows/ci-ffi-ruby.yml | 282 ++++++++++++ .github/workflows/python.yml | 136 ------ .github/workflows/ruby.yml | 216 --------- Cargo.toml | 8 +- README.md | 9 +- examples/transform.rs | 96 ++++ .../pyroscope_pprofrs/Cargo.toml | 5 +- .../pyroscope_pprofrs/src/lib.rs | 11 +- pyroscope_backends/pyroscope_pyspy/Cargo.toml | 4 +- pyroscope_backends/pyroscope_pyspy/src/lib.rs | 29 +- pyroscope_backends/pyroscope_rbspy/Cargo.toml | 4 +- pyroscope_backends/pyroscope_rbspy/src/lib.rs | 30 +- pyroscope_cli/CHANGELOG.md | 2 +- pyroscope_cli/Cargo.lock | 435 +++++++++--------- pyroscope_cli/Cargo.toml | 14 +- pyroscope_cli/src/cli/lib.rs | 30 +- pyroscope_cli/src/core/profiler.rs | 42 +- .../src/resources/default_config.toml | 3 +- pyroscope_cli/src/utils/app_config.rs | 21 +- pyroscope_ffi/python/README.md | 61 ++- pyroscope_ffi/python/lib/src/lib.rs | 4 +- pyroscope_ffi/python/pyroscope/__init__.py | 12 +- pyroscope_ffi/python/scripts/tests/test.py | 61 +++ pyroscope_ffi/ruby/README.md | 80 ++-- pyroscope_ffi/ruby/ext/rbspy/src/lib.rs | 102 +++- pyroscope_ffi/ruby/lib/pyroscope.rb | 35 +- pyroscope_ffi/ruby/lib/pyroscope/version.rb | 2 +- pyroscope_ffi/ruby/pyroscope.gemspec | 18 +- pyroscope_ffi/ruby/scripts/tests/test.rb | 59 +++ src/backend/types.rs | 10 + src/pyroscope.rs | 46 +- src/session.rs | 19 +- 33 files changed, 1372 insertions(+), 733 deletions(-) create mode 100644 .github/workflows/ci-ffi-python.yml create mode 100644 .github/workflows/ci-ffi-ruby.yml delete mode 100644 .github/workflows/python.yml delete mode 100644 .github/workflows/ruby.yml create mode 100644 examples/transform.rs create mode 100755 pyroscope_ffi/python/scripts/tests/test.py create mode 100755 pyroscope_ffi/ruby/scripts/tests/test.rb diff --git a/.github/workflows/ci-ffi-python.yml b/.github/workflows/ci-ffi-python.yml new file mode 100644 index 00000000..64a02f79 --- /dev/null +++ b/.github/workflows/ci-ffi-python.yml @@ -0,0 +1,219 @@ +name: Python Package + +on: + push: + paths: + - 'pyroscope_ffi/python/**' + - '.github/workflows/ci-ffi-python.yml' + branches: + - '**' + pull_request: + paths: + - 'pyroscope_ffi/python/**' + - '.github/workflows/ci-ffi-python.yml' + branches: + - '**' + +jobs: + linux-build: + strategy: + fail-fast: false + matrix: + build-arch: + - manylinux2010_x86_64 + + name: Linux - ${{ matrix.build-arch }} + runs-on: ubuntu-latest + + steps: + - uses: AutoModality/action-clean@v1 + - uses: actions/checkout@v2 + with: + submodules: recursive + + - if: matrix.build-arch == 'manylinux2014_aarch64' + uses: docker/setup-qemu-action@v1 + with: + platforms: arm64 + + - name: Build in Docker + run: pyroscope_ffi/python/scripts/docker.sh + env: + BUILD_ARCH: ${{ matrix.build-arch }} + + - uses: actions/upload-artifact@v2 + with: + name: "linux.whl" + path: pyroscope_ffi/python/dist/* + + linux-test: + strategy: + fail-fast: false + matrix: + PYROSCOPE_DETECT_SUBPROCESSES: [1, 0] + PYROSCOPE_ONCPU: [1, 0] + PYROSCOPE_GIL_ONLY: [1, 0] + PYROSCOPE_NATIVE: [1, 0] + PYTHON_VERSION: ['2.7', '3.7', '3.8', '3.9', '3.10'] + needs: ['linux-build'] + name: Linux Test + runs-on: ubuntu-latest + steps: + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.PYTHON_VERSION }} + architecture: x64 + - uses: actions/download-artifact@master + with: + name: "linux.whl" + path: "${{github.workspace}}/python" + + - run: "cd ${{ github.workspace }}/python && ls -l" + - run: "cd ${{ github.workspace }}/python && pip install *.whl" + - uses: actions/checkout@v2 + with: + submodules: recursive + - name: Run Python Script + run: pyroscope_ffi/python/scripts/tests/test.py + env: + PYROSCOPE_RUN_ID: ${{ github.run_id }} + PYROSCOPE_ARCH: x86-64-linux + PYROSCOPE_API_TOKEN: ${{ secrets.PYROSCOPE_API_TOKEN }} + PYROSCOPE_DETECT_SUBPROCESSES: ${{ matrix.PYROSCOPE_DETECT_SUBPROCESSES }} + PYROSCOPE_ONCPU: ${{ matrix.PYROSCOPE_ONCPU }} + PYROSCOPE_GIL_ONLY: ${{ matrix.PYROSCOPE_GIL_ONLY }} + PYROSCOPE_NATIVE: ${{ matrix.PYROSCOPE_NATIVE }} + PYTHON_VERSION: ${{ matrix.PYTHON_VERSION }} + + linux-arm-build: + strategy: + fail-fast: false + matrix: + build-arch: + - manylinux2014_aarch64 + + name: Linux - ${{ matrix.build-arch }} + runs-on: [self-hosted, Linux, ARM64] + + steps: + - uses: AutoModality/action-clean@v1 + - uses: actions/checkout@v2 + with: + submodules: recursive + + - name: Build in Docker + run: pyroscope_ffi/python/scripts/docker.sh + env: + BUILD_ARCH: ${{ matrix.build-arch }} + + - uses: actions/upload-artifact@v2 + with: + name: "linux-arm.whl" + path: pyroscope_ffi/python/dist/* + + macos-build: + strategy: + fail-fast: false + matrix: + include: + - macos-version: "11.0" + target: x86_64-apple-darwin + py-platform: macosx-11_0_x86_64 + - macos-version: "11.0" + target: aarch64-apple-darwin + py-platform: macosx-11_0_arm64 + + name: macOS - ${{ matrix.py-platform }} + runs-on: macos-${{ matrix.macos-version }} + + steps: + - uses: actions/checkout@v2 + + - uses: actions-rs/toolchain@v1 + with: + toolchain: stable + target: ${{ matrix.target }} + profile: minimal + override: true + + - uses: actions/setup-python@v2 + with: + python-version: 3.9 + + + - name: Build Wheel + run: | + pip install wheel + python3 setup.py bdist_wheel -p ${{ matrix.py-platform }} + working-directory: pyroscope_ffi/python + env: + CARGO_BUILD_TARGET: ${{ matrix.target }} + + - uses: actions/upload-artifact@v2 + with: + name: ${{ matrix.target }} + path: pyroscope_ffi/python/dist/* + + macos-intel-test: + strategy: + fail-fast: false + matrix: + PYROSCOPE_DETECT_SUBPROCESSES: [1, 0] + PYROSCOPE_ONCPU: [1, 0] + PYROSCOPE_GIL_ONLY: [1, 0] + PYROSCOPE_NATIVE: [1, 0] + PYTHON_VERSION: ['2.7', '3.7', '3.8', '3.9', '3.10'] + needs: ['macos-build'] + name: Macos Test + runs-on: macos-11.0 + steps: + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.PYTHON_VERSION }} + architecture: x64 + - uses: actions/download-artifact@master + with: + name: x86_64-apple-darwin + path: "${{github.workspace}}/python" + + - run: "python --version" + - run: "python3 --version" + - run: "cd ${{ github.workspace }}/python && ls -l" + - run: "cd ${{ github.workspace }}/python && pip3 install *.whl" + - uses: actions/checkout@v2 + with: + submodules: recursive + - name: Run Python Script + run: pyroscope_ffi/python/scripts/tests/test.py + env: + PYROSCOPE_RUN_ID: ${{ github.run_id }} + PYROSCOPE_ARCH: x86-64-apple-darwin + PYROSCOPE_API_TOKEN: ${{ secrets.PYROSCOPE_API_TOKEN }} + PYROSCOPE_DETECT_SUBPROCESSES: ${{ matrix.PYROSCOPE_DETECT_SUBPROCESSES }} + PYROSCOPE_ONCPU: ${{ matrix.PYROSCOPE_ONCPU }} + PYROSCOPE_GIL_ONLY: ${{ matrix.PYROSCOPE_GIL_ONLY }} + PYROSCOPE_NATIVE: ${{ matrix.PYROSCOPE_NATIVE }} + PYTHON_VERSION: ${{ matrix.PYTHON_VERSION }} + + sdist-build: + name: sdist + runs-on: ubuntu-latest + + steps: + - uses: AutoModality/action-clean@v1 + - uses: actions/checkout@v2 + + - uses: actions/setup-python@v2 + with: + python-version: 3.7 + + - name: Build sdist + run: python setup.py sdist + working-directory: pyroscope_ffi/python + + - uses: actions/upload-artifact@v2 + with: + name: "sdist.whl" + path: pyroscope_ffi/python/dist/* diff --git a/.github/workflows/ci-ffi-ruby.yml b/.github/workflows/ci-ffi-ruby.yml new file mode 100644 index 00000000..584ac692 --- /dev/null +++ b/.github/workflows/ci-ffi-ruby.yml @@ -0,0 +1,282 @@ +name: Ruby Package + +on: + push: + paths: + - 'pyroscope_ffi/ruby/**' + - '.github/workflows/ci-ffi-ruby.yml' + branches: + - '**' + pull_request: + paths: + - 'pyroscope_ffi/ruby/**' + - '.github/workflows/ci-ffi-ruby.yml' + branches: + - '**' + +jobs: + linux-build: + strategy: + fail-fast: false + matrix: + include: + - build-arch: x86_64 + target: x86_64-unknown-linux-gnu + + name: Linux - ${{ matrix.build-arch }} + runs-on: ubuntu-latest + + steps: + - uses: AutoModality/action-clean@v1 + - uses: actions/checkout@v2 + + - uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.1' + + - name: Install bundles + run: bundle + working-directory: pyroscope_ffi/ruby + + - name: Update lock files + run: cargo update + working-directory: pyroscope_ffi/ruby/ext/rbspy + + - name: Update lock files + run: cargo update + working-directory: pyroscope_ffi/ruby/ext/thread_id + + - name: Build native extensions + run: rake thread_id_install + working-directory: pyroscope_ffi/ruby + + - name: Generate extra libraries + run: BUILD_ARCH=manylinux2010_x86_64 ./pyroscope_ffi/ruby/scripts/docker.sh + + - name: Copy generated extra libraries + run: mkdir -p lib/rbspy && cp ./elflib/rbspy/wheelhouse/rbspy-1.0.0/rbspy/_native__lib.cpython-37m-x86_64-linux-gnu.so lib/rbspy/rbspy.so + working-directory: pyroscope_ffi/ruby + + - name: Copy generated extra libraries + run: cp -r ./elflib/rbspy/wheelhouse/rbspy-1.0.0/rbspy.libs lib/rbspy.libs + working-directory: pyroscope_ffi/ruby + + - name: Build linux gem + run: rake x86_64_linux:gem + working-directory: pyroscope_ffi/ruby + + + - uses: actions/upload-artifact@v2 + with: + name: "linux.gem" + path: pyroscope_ffi/ruby/pkg/*.gem + + linux-test: + strategy: + fail-fast: false + matrix: + PYROSCOPE_DETECT_SUBPROCESSES: [1, 0] + PYROSCOPE_ONCPU: [1, 0] + RUBY_VERSION: ['2.6', '2.7', '3.0', '3.1'] + needs: ['linux-build'] + name: Linux Test + runs-on: ubuntu-latest + steps: + - uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.RUBY_VERSION }} + - uses: actions/download-artifact@master + with: + name: "linux.gem" + path: "${{github.workspace}}/ruby" + - run: "cd ${{ github.workspace }}/ruby && ls -l" + - run: "cd ${{ github.workspace }}/ruby && gem install *.gem" + - uses: actions/checkout@v2 + with: + submodules: recursive + - name: Run Ruby Script + run: pyroscope_ffi/ruby/scripts/tests/test.rb + env: + PYROSCOPE_RUN_ID: ${{ github.run_id }} + PYROSCOPE_ARCH: x86-64-linux + PYROSCOPE_API_TOKEN: ${{ secrets.PYROSCOPE_API_TOKEN }} + PYROSCOPE_DETECT_SUBPROCESSES: ${{ matrix.PYROSCOPE_DETECT_SUBPROCESSES }} + PYROSCOPE_ONCPU: ${{ matrix.PYROSCOPE_ONCPU }} + RUBY_VERSION: ${{ matrix.RUBY_VERSION }} + + #linux-arm: + #strategy: + #fail-fast: false + #matrix: + #include: + #- build-arch: aarch64 + #target: aarch64-unknown-linux-gnu + + #name: Linux - ${{ matrix.build-arch }} + #runs-on: [self-hosted, Linux, ARM64] + + #steps: + #- uses: AutoModality/action-clean@v1 + + #- uses: actions/checkout@v2 + + #- name: Install bundles + #run: bundle + #working-directory: pyroscope_ffi/ruby + + #- name: Update lock files + #run: cargo update + #working-directory: pyroscope_ffi/ruby/ext/rbspy + + #- name: Update lock files + #run: cargo update + #working-directory: pyroscope_ffi/ruby/ext/thread_id + + #- name: Build native extensions + #run: rake thread_id_install + #working-directory: pyroscope_ffi/ruby + + #- name: Generate extra libraries + #run: BUILD_ARCH=manylinux2014_aarch64 ./pyroscope_ffi/ruby/scripts/docker.sh + + #- name: Copy generated extra libraries + #run: mkdir -p lib/rbspy && cp ./elflib/rbspy/wheelhouse/rbspy-1.0.0/rbspy/_native__lib.cpython-37m-aarch64-linux-gnu.so lib/rbspy/rbspy.so + #working-directory: pyroscope_ffi/ruby + + #- name: Copy generated extra libraries + #run: cp -r ./elflib/rbspy/wheelhouse/rbspy-1.0.0/rbspy.libs lib/rbspy.libs + #working-directory: pyroscope_ffi/ruby + + #- name: Build linux gem + #run: rake aarch64_linux:gem + #working-directory: pyroscope_ffi/ruby + + #- uses: actions/upload-artifact@v2 + #with: + #name: ${{ github.sha }} + #path: pyroscope_ffi/ruby/pkg/*.gem + + macos-build: + strategy: + fail-fast: false + matrix: + include: + - macos-version: "11.0" + target: x86_64-apple-darwin + py-platform: macosx-11_0_x86_64 + - macos-version: "11.0" + target: aarch64-apple-darwin + py-platform: macosx-11_0_arm64 + + name: macOS - ${{ matrix.platform }} + runs-on: macos-${{ matrix.macos-version }} + + env: + RUST_TARGET: ${{ matrix.target }} + + steps: + - uses: actions/checkout@v2 + + - uses: actions-rs/toolchain@v1 + with: + toolchain: stable + target: ${{ matrix.target }} + profile: minimal + override: true + + - uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.1' + + - name: Install bundles + run: bundle + working-directory: pyroscope_ffi/ruby + + - name: Update lock files + run: cargo update + working-directory: pyroscope_ffi/ruby/ext/rbspy + + - name: Update lock files + run: cargo update + working-directory: pyroscope_ffi/ruby/ext/thread_id + + - name: Build native extensions + run: rake rbspy_install + working-directory: pyroscope_ffi/ruby + + - name: Build native extensions + run: rake thread_id_install + working-directory: pyroscope_ffi/ruby + + - if: matrix.target == 'x86_64-apple-darwin' + name: Build macos gem + run: rake x86_64_darwin:gem + working-directory: pyroscope_ffi/ruby + + - if: matrix.target == 'aarch64-apple-darwin' + name: Build macos gem + run: rake arm64_darwin:gem + working-directory: pyroscope_ffi/ruby + + - uses: actions/upload-artifact@v2 + with: + name: ${{ matrix.target }} + path: pyroscope_ffi/ruby/pkg/*.gem + + macos-intel-test: + strategy: + fail-fast: false + matrix: + PYROSCOPE_DETECT_SUBPROCESSES: [1, 0] + PYROSCOPE_ONCPU: [1, 0] + RUBY_VERSION: ['2.6', '2.7', '3.0', '3.1'] + needs: ['macos-build'] + name: macOS Test + runs-on: macos-11.0 + steps: + - uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.RUBY_VERSION }} + - uses: actions/download-artifact@master + with: + name: x86_64-apple-darwin + path: "${{github.workspace}}/ruby" + - run: "cd ${{ github.workspace }}/ruby && ls -l" + - run: "cd ${{ github.workspace }}/ruby && gem install *.gem" + - uses: actions/checkout@v2 + with: + submodules: recursive + - name: Run Ruby Script + run: pyroscope_ffi/ruby/scripts/tests/test.rb + env: + PYROSCOPE_RUN_ID: ${{ github.run_id }} + PYROSCOPE_ARCH: x86-64-apple-darwin + PYROSCOPE_API_TOKEN: ${{ secrets.PYROSCOPE_API_TOKEN }} + PYROSCOPE_DETECT_SUBPROCESSES: ${{ matrix.PYROSCOPE_DETECT_SUBPROCESSES }} + PYROSCOPE_ONCPU: ${{ matrix.PYROSCOPE_ONCPU }} + RUBY_VERSION: ${{ matrix.RUBY_VERSION }} + + #source: + #name: source + #runs-on: ubuntu-latest + + #steps: + #- uses: AutoModality/action-clean@v1 + #- uses: actions/checkout@v2 + + #- uses: ruby/setup-ruby@v1 + #with: + #ruby-version: '3.1' + + #- name: Install bundles + #run: bundle + #working-directory: pyroscope_ffi/ruby + + #- name: Build source gem + #run: rake source:gem + #working-directory: pyroscope_ffi/ruby + + #- uses: actions/upload-artifact@v2 + #with: + #name: ${{ github.sha }} + #path: pyroscope_ffi/ruby/pkg/*.gem diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml deleted file mode 100644 index 30aa78a5..00000000 --- a/.github/workflows/python.yml +++ /dev/null @@ -1,136 +0,0 @@ -name: Python Package - -on: - push: - paths: - - 'pyroscope_ffi/python/**' - - '.github/workflows/python.yml' - branches: - - '**' - pull_request: - paths: - - 'pyroscope_ffi/python/**' - - '.github/workflows/python.yml' - branches: - - '**' - -jobs: - linux: - strategy: - fail-fast: false - matrix: - build-arch: - - manylinux2010_x86_64 - - name: Linux - ${{ matrix.build-arch }} - runs-on: ubuntu-latest - - steps: - - uses: AutoModality/action-clean@v1 - - uses: actions/checkout@v2 - with: - submodules: recursive - - - if: matrix.build-arch == 'manylinux2014_aarch64' - uses: docker/setup-qemu-action@v1 - with: - platforms: arm64 - - - name: Build in Docker - run: pyroscope_ffi/python/scripts/docker.sh - env: - BUILD_ARCH: ${{ matrix.build-arch }} - - - uses: actions/upload-artifact@v2 - with: - name: ${{ github.sha }} - path: pyroscope_ffi/python/dist/* - - linux-arm: - strategy: - fail-fast: false - matrix: - build-arch: - - manylinux2014_aarch64 - - name: Linux - ${{ matrix.build-arch }} - runs-on: [self-hosted, Linux, ARM64] - - steps: - - uses: AutoModality/action-clean@v1 - - uses: actions/checkout@v2 - with: - submodules: recursive - - - name: Build in Docker - run: pyroscope_ffi/python/scripts/docker.sh - env: - BUILD_ARCH: ${{ matrix.build-arch }} - - - uses: actions/upload-artifact@v2 - with: - name: ${{ github.sha }} - path: pyroscope_ffi/python/dist/* - - macos: - strategy: - fail-fast: false - matrix: - include: - - macos-version: "10.15" - target: x86_64-apple-darwin - py-platform: macosx-10_15_x86_64 - - macos-version: "11.0" - target: aarch64-apple-darwin - py-platform: macosx-11_0_arm64 - - name: macOS - ${{ matrix.py-platform }} - runs-on: macos-${{ matrix.macos-version }} - - steps: - - uses: actions/checkout@v2 - - - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - target: ${{ matrix.target }} - profile: minimal - override: true - - - uses: actions/setup-python@v2 - with: - python-version: 3.9 - - - name: Build Wheel - run: | - pip install wheel - python setup.py bdist_wheel -p ${{ matrix.py-platform }} - working-directory: pyroscope_ffi/python - env: - CARGO_BUILD_TARGET: ${{ matrix.target }} - - - uses: actions/upload-artifact@v2 - with: - name: ${{ github.sha }} - path: pyroscope_ffi/python/dist/* - - sdist: - name: sdist - runs-on: ubuntu-latest - - steps: - - uses: AutoModality/action-clean@v1 - - uses: actions/checkout@v2 - - - uses: actions/setup-python@v2 - with: - python-version: 3.7 - - - name: Build sdist - run: python setup.py sdist - working-directory: pyroscope_ffi/python - - - uses: actions/upload-artifact@v2 - with: - name: ${{ github.sha }} - path: pyroscope_ffi/python/dist/* diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml deleted file mode 100644 index 764a6ce7..00000000 --- a/.github/workflows/ruby.yml +++ /dev/null @@ -1,216 +0,0 @@ -name: Ruby Package - -on: - push: - paths: - - 'pyroscope_ffi/ruby/**' - - '.github/workflows/ruby.yml' - branches: - - '**' - pull_request: - paths: - - 'pyroscope_ffi/ruby/**' - - '.github/workflows/ruby.yml' - branches: - - '**' - -jobs: - linux: - strategy: - fail-fast: false - matrix: - include: - - build-arch: x86_64 - target: x86_64-unknown-linux-gnu - - name: Linux - ${{ matrix.build-arch }} - runs-on: ubuntu-latest - - steps: - - uses: AutoModality/action-clean@v1 - - uses: actions/checkout@v2 - - - uses: ruby/setup-ruby@v1 - with: - ruby-version: '3.1' - - - name: Install bundles - run: bundle - working-directory: pyroscope_ffi/ruby - - - name: Update lock files - run: cargo update - working-directory: pyroscope_ffi/ruby/ext/rbspy - - - name: Update lock files - run: cargo update - working-directory: pyroscope_ffi/ruby/ext/thread_id - - - name: Build native extensions - run: rake thread_id_install - working-directory: pyroscope_ffi/ruby - - - name: Generate extra libraries - run: BUILD_ARCH=manylinux2010_x86_64 ./pyroscope_ffi/ruby/scripts/docker.sh - - - name: Copy generated extra libraries - run: mkdir -p lib/rbspy && cp ./elflib/rbspy/wheelhouse/rbspy-1.0.0/rbspy/_native__lib.cpython-37m-x86_64-linux-gnu.so lib/rbspy/rbspy.so - working-directory: pyroscope_ffi/ruby - - - name: Copy generated extra libraries - run: cp -r ./elflib/rbspy/wheelhouse/rbspy-1.0.0/rbspy.libs lib/rbspy.libs - working-directory: pyroscope_ffi/ruby - - - name: Build linux gem - run: rake x86_64_linux:gem - working-directory: pyroscope_ffi/ruby - - - - uses: actions/upload-artifact@v2 - with: - name: ${{ github.sha }} - path: pyroscope_ffi/ruby/pkg/*.gem - - linux-arm: - strategy: - fail-fast: false - matrix: - include: - - build-arch: aarch64 - target: aarch64-unknown-linux-gnu - - name: Linux - ${{ matrix.build-arch }} - runs-on: [self-hosted, Linux, ARM64] - - steps: - - uses: AutoModality/action-clean@v1 - - - uses: actions/checkout@v2 - - - name: Install bundles - run: bundle - working-directory: pyroscope_ffi/ruby - - - name: Update lock files - run: cargo update - working-directory: pyroscope_ffi/ruby/ext/rbspy - - - name: Update lock files - run: cargo update - working-directory: pyroscope_ffi/ruby/ext/thread_id - - - name: Build native extensions - run: rake thread_id_install - working-directory: pyroscope_ffi/ruby - - - name: Generate extra libraries - run: BUILD_ARCH=manylinux2014_aarch64 ./pyroscope_ffi/ruby/scripts/docker.sh - - - name: Copy generated extra libraries - run: mkdir -p lib/rbspy && cp ./elflib/rbspy/wheelhouse/rbspy-1.0.0/rbspy/_native__lib.cpython-37m-aarch64-linux-gnu.so lib/rbspy/rbspy.so - working-directory: pyroscope_ffi/ruby - - - name: Copy generated extra libraries - run: cp -r ./elflib/rbspy/wheelhouse/rbspy-1.0.0/rbspy.libs lib/rbspy.libs - working-directory: pyroscope_ffi/ruby - - - name: Build linux gem - run: rake aarch64_linux:gem - working-directory: pyroscope_ffi/ruby - - - uses: actions/upload-artifact@v2 - with: - name: ${{ github.sha }} - path: pyroscope_ffi/ruby/pkg/*.gem - - macos: - strategy: - fail-fast: false - matrix: - include: - - macos-version: "10.15" - target: x86_64-apple-darwin - py-platform: macosx-10_15_x86_64 - - macos-version: "11.0" - target: aarch64-apple-darwin - py-platform: macosx-11_0_arm64 - - name: macOS - ${{ matrix.platform }} - runs-on: macos-${{ matrix.macos-version }} - - env: - RUST_TARGET: ${{ matrix.target }} - - steps: - - uses: actions/checkout@v2 - - - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - target: ${{ matrix.target }} - profile: minimal - override: true - - - uses: ruby/setup-ruby@v1 - with: - ruby-version: '3.1' - - - name: Install bundles - run: bundle - working-directory: pyroscope_ffi/ruby - - - name: Update lock files - run: cargo update - working-directory: pyroscope_ffi/ruby/ext/rbspy - - - name: Update lock files - run: cargo update - working-directory: pyroscope_ffi/ruby/ext/thread_id - - - name: Build native extensions - run: rake rbspy_install - working-directory: pyroscope_ffi/ruby - - - name: Build native extensions - run: rake thread_id_install - working-directory: pyroscope_ffi/ruby - - - if: matrix.target == 'x86_64-apple-darwin' - name: Build macos gem - run: rake x86_64_darwin:gem - working-directory: pyroscope_ffi/ruby - - - if: matrix.target == 'aarch64-apple-darwin' - name: Build macos gem - run: rake arm64_darwin:gem - working-directory: pyroscope_ffi/ruby - - - uses: actions/upload-artifact@v2 - with: - name: ${{ github.sha }} - path: pyroscope_ffi/ruby/pkg/*.gem - - source: - name: source - runs-on: ubuntu-latest - - steps: - - uses: AutoModality/action-clean@v1 - - uses: actions/checkout@v2 - - - uses: ruby/setup-ruby@v1 - with: - ruby-version: '3.1' - - - name: Install bundles - run: bundle - working-directory: pyroscope_ffi/ruby - - - name: Build source gem - run: rake source:gem - working-directory: pyroscope_ffi/ruby - - - uses: actions/upload-artifact@v2 - with: - name: ${{ github.sha }} - path: pyroscope_ffi/ruby/pkg/*.gem diff --git a/Cargo.toml b/Cargo.toml index 8f18a360..691874ce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ Pyroscope Profiler Agent for continuous profiling of Rust, Python and Ruby appli """ keywords = ["pyroscope", "profiler", "profiling", "pprof"] authors = ["Abid Omar "] -version = "0.5.3" +version = "0.5.4" edition = "2021" license = "Apache-2.0" homepage = "https://pyroscope.io/docs/rust" @@ -13,9 +13,9 @@ documentation = "https://docs.rs/pyroscope" repository = "https://github.com/pyroscope-io/pyroscope-rs" readme = "README.md" autobins = false -autoexamples = true -autotests = true -autobenches = true +autoexamples = true +autotests = true +autobenches = true [workspace] members = [ diff --git a/README.md b/README.md index 6ad6da1e..9815a3c7 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ Add this to your `Cargo.toml`: ```toml [dependencies] -pyroscope = "0.5.3" +pyroscope = "0.5.4" pyroscope_pprofrs = "0.2" ``` @@ -79,6 +79,13 @@ The Pyroscope Agent doesn't do any profiling. The agent role is to orchasrate a - [rbspy](pyroscope_backends/pyroscope_rbspy): Ruby Profiler. A wrapper around [rbspy](https://rbspy.github.io/). - [py-spy](pyroscope_backends/pyroscope_pyspy): Python Profiler. A wrapper around [py-spy](https://github.com/benfred/py-spy). +### Native Integration + +Pyroscope can be used directly from your projects with native integration. No agent or external programs are required. + +- [Python](https://pypi.org/project/pyroscope-io/): Python Package. [Readme](https://github.com/pyroscope-io/pyroscope-rs/tree/main/pyroscope_ffi/python#readme) - [Documentation](https://pyroscope.io/docs/python/) +- [Ruby](https://rubygems.org/gems/pyroscope): Ruby Gem. [Readme](https://github.com/pyroscope-io/pyroscope-rs/tree/main/pyroscope_ffi/ruby#readme) - [Documentation](https://pyroscope.io/docs/ruby/) + ### Limitations diff --git a/examples/transform.rs b/examples/transform.rs new file mode 100644 index 00000000..a5c3bf6e --- /dev/null +++ b/examples/transform.rs @@ -0,0 +1,96 @@ +extern crate pyroscope; + +use pyroscope::{ + backend::{Report, StackFrame}, + PyroscopeAgent, Result, +}; +use pyroscope_pprofrs::{pprof_backend, PprofConfig}; +use std::hash::{Hash, Hasher}; + +fn hash_rounds(n: u64) -> u64 { + let hash_str = "Some string to hash"; + let mut default_hasher = std::collections::hash_map::DefaultHasher::new(); + + for _ in 0..n { + for _ in 0..1000 { + default_hasher.write(hash_str.as_bytes()); + } + hash_str.hash(&mut default_hasher); + } + + n +} + +pub fn transform_report(report: Report) -> Report { + let data = report + .iter() + .map(|(stacktrace, count)| { + let new_frames = stacktrace + .iter() + .map(|frame| { + let frame = frame.clone(); + // something + StackFrame::new( + frame.module, + frame.name, + frame.filename, + frame.relative_path, + frame.absolute_path, + frame.line, + ) + }) + .collect(); + + let mut mystack = stacktrace.to_owned(); + + mystack.frames = new_frames; + + (mystack, count.to_owned()) + }) + .collect(); + + let new_report = Report::new(data).metadata(report.metadata.clone()); + + new_report +} +fn main() -> Result<()> { + let agent = PyroscopeAgent::builder("http://localhost:4040", "example.transform") + .backend(pprof_backend(PprofConfig::new().sample_rate(100))) + .tags([("TagA", "ValueA"), ("TagB", "ValueB")].to_vec()) + .func(transform_report) + .build()?; + + // Show start time + let start = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap() + .as_secs(); + println!("Start Time: {}", start); + + // Start Agent + let agent_running = agent.start()?; + + let _result = hash_rounds(300_000); + + // Show stop time + let stop = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap() + .as_secs(); + println!("Stop Time: {}", stop); + + // Stop Agent + let agent_ready = agent_running.stop()?; + + // Shutdown the Agent + agent_ready.shutdown(); + + // Show program exit time + let exit = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap() + .as_secs(); + println!("Exit Time: {}", exit); + + Ok(()) +} diff --git a/pyroscope_backends/pyroscope_pprofrs/Cargo.toml b/pyroscope_backends/pyroscope_pprofrs/Cargo.toml index 668be761..1e6472e7 100644 --- a/pyroscope_backends/pyroscope_pprofrs/Cargo.toml +++ b/pyroscope_backends/pyroscope_pprofrs/Cargo.toml @@ -5,7 +5,7 @@ pprof-rs backend for Pyroscope Profiler. """ keywords = ["pyroscope", "profiler", "pprof-rs"] authors = ["Abid Omar "] -version = "0.2.3" +version = "0.2.4" edition = "2021" license = "Apache-2.0" homepage = "https://pyroscope.io" @@ -16,8 +16,9 @@ readme = "README.md" [dependencies] pprof = "0.10.0" -pyroscope = {version = "0.5.3", path = "../../" } +pyroscope = {version = "0.5.4", path = "../../" } thiserror ="1.0" +log = "0.4" [profile.dev] opt-level=0 diff --git a/pyroscope_backends/pyroscope_pprofrs/src/lib.rs b/pyroscope_backends/pyroscope_pprofrs/src/lib.rs index f74cc478..7ba632c1 100644 --- a/pyroscope_backends/pyroscope_pprofrs/src/lib.rs +++ b/pyroscope_backends/pyroscope_pprofrs/src/lib.rs @@ -13,8 +13,10 @@ use std::{ sync::{Arc, Mutex}, }; +const LOG_TAG: &str = "Pyroscope::Pprofrs"; + pub fn pprof_backend(config: PprofConfig) -> BackendImpl { - let backend_config = config.backend_config.clone(); + let backend_config = config.backend_config; BackendImpl::new(Box::new(Pprof::new(config)), Some(backend_config)) } @@ -101,11 +103,11 @@ impl std::fmt::Debug for Pprof<'_> { impl<'a> Pprof<'a> { /// Create a new Pprof Backend pub fn new(config: PprofConfig) -> Self { - let backend_config = config.backend_config.clone(); + let backend_config = config.backend_config; Pprof { buffer: Arc::new(Mutex::new(StackBuffer::default())), config, - backend_config: backend_config, + backend_config, inner_builder: Arc::new(Mutex::new(None)), guard: Arc::new(Mutex::new(None)), ruleset: Ruleset::default(), @@ -127,6 +129,7 @@ impl Backend for Pprof<'_> { } fn shutdown(self: Box) -> Result<()> { + log::trace!(target: LOG_TAG, "Shutting down sampler thread"); //drop(self.guard.take()); Ok(()) @@ -166,7 +169,7 @@ impl Backend for Pprof<'_> { Ok(reports) } - fn set_config(&self, config: BackendConfig) {} + fn set_config(&self, _config: BackendConfig) {} fn get_config(&self) -> Result { Ok(self.backend_config) diff --git a/pyroscope_backends/pyroscope_pyspy/Cargo.toml b/pyroscope_backends/pyroscope_pyspy/Cargo.toml index 1c5db995..1abd9d2f 100644 --- a/pyroscope_backends/pyroscope_pyspy/Cargo.toml +++ b/pyroscope_backends/pyroscope_pyspy/Cargo.toml @@ -5,7 +5,7 @@ pyspy backend for Pyroscope Profiler. """ keywords = ["pyroscope", "profiler", "pyspy"] authors = ["Abid Omar "] -version = "0.2.3" +version = "0.2.4" edition = "2021" license = "Apache-2.0" homepage = "https://pyroscope.io" @@ -15,7 +15,7 @@ readme = "README.md" [dependencies] py-spy = "0.3.12" -pyroscope = { version = "0.5.3", path = "../../" } +pyroscope = { version = "0.5.4", path = "../../" } thiserror ="1.0" log = "0.4" diff --git a/pyroscope_backends/pyroscope_pyspy/src/lib.rs b/pyroscope_backends/pyroscope_pyspy/src/lib.rs index 7d2174da..e466e8ca 100644 --- a/pyroscope_backends/pyroscope_pyspy/src/lib.rs +++ b/pyroscope_backends/pyroscope_pyspy/src/lib.rs @@ -20,7 +20,7 @@ const LOG_TAG: &str = "Pyroscope::Pyspy"; /// Short-hand function for creating a new Pyspy backend. pub fn pyspy_backend(config: PyspyConfig) -> BackendImpl { // Clone BackendConfig to pass to the backend object. - let backend_config = config.backend_config.clone(); + let backend_config = config.backend_config; BackendImpl::new(Box::new(Pyspy::new(config)), Some(backend_config)) } @@ -39,9 +39,9 @@ pub struct PyspyConfig { /// Profiling duration (None for infinite) time_limit: Option, /// Include subprocesses - with_subprocesses: bool, + detect_subprocesses: bool, /// Include idle time - include_idle: bool, + oncpu: bool, /// Detect Python GIL gil_only: bool, /// Profile native C extensions @@ -56,8 +56,8 @@ impl Default for PyspyConfig { backend_config: BackendConfig::default(), lock_process: py_spy::config::LockingStrategy::NonBlocking, time_limit: None, - with_subprocesses: false, - include_idle: false, + detect_subprocesses: false, + oncpu: false, gil_only: false, native: false, } @@ -138,19 +138,16 @@ impl PyspyConfig { } /// Include subprocesses - pub fn with_subprocesses(self, with_subprocesses: bool) -> Self { + pub fn detect_subprocesses(self, detect_subprocesses: bool) -> Self { PyspyConfig { - with_subprocesses, + detect_subprocesses, ..self } } /// Include idle time - pub fn include_idle(self, include_idle: bool) -> Self { - PyspyConfig { - include_idle, - ..self - } + pub fn oncpu(self, oncpu: bool) -> Self { + PyspyConfig { oncpu, ..self } } /// Detect Python GIL @@ -217,7 +214,7 @@ impl Backend for Pyspy { Ok(self.config.sample_rate) } - fn set_config(&self, config: BackendConfig) {} + fn set_config(&self, _config: BackendConfig) {} fn get_config(&self) -> Result { Ok(self.config.backend_config) @@ -256,9 +253,9 @@ impl Backend for Pyspy { native: self.config.native, pid: self.config.pid, sampling_rate: self.config.sample_rate as u64, - include_idle: self.config.include_idle, + include_idle: self.config.oncpu, include_thread_ids: true, - subprocesses: self.config.with_subprocesses, + subprocesses: self.config.detect_subprocesses, gil_only: self.config.gil_only, duration, ..Config::default() @@ -280,7 +277,7 @@ impl Backend for Pyspy { // create a new ruleset reference let ruleset = self.ruleset.clone(); - let backend_config = self.config.backend_config.clone(); + let backend_config = self.config.backend_config; self.sampler_thread = Some(std::thread::spawn(move || { // Get PID diff --git a/pyroscope_backends/pyroscope_rbspy/Cargo.toml b/pyroscope_backends/pyroscope_rbspy/Cargo.toml index f7ac0c7a..bfee44c9 100644 --- a/pyroscope_backends/pyroscope_rbspy/Cargo.toml +++ b/pyroscope_backends/pyroscope_rbspy/Cargo.toml @@ -5,7 +5,7 @@ rbspy backend for Pyroscope Profiler. """ keywords = ["pyroscope", "profiler", "rbspy"] authors = ["Abid Omar "] -version = "0.2.2" +version = "0.2.3" edition = "2021" license = "Apache-2.0" homepage = "https://pyroscope.io" @@ -15,7 +15,7 @@ readme = "README.md" [dependencies] rbspy= {package = "rbspy-oncpu", version = "0.12.1"} -pyroscope = { version = "0.5.3", path = "../../" } +pyroscope = { version = "0.5.4", path = "../../" } thiserror ="1.0" log = "0.4" anyhow = "1.0.56" diff --git a/pyroscope_backends/pyroscope_rbspy/src/lib.rs b/pyroscope_backends/pyroscope_rbspy/src/lib.rs index 42b02307..831a50ed 100644 --- a/pyroscope_backends/pyroscope_rbspy/src/lib.rs +++ b/pyroscope_backends/pyroscope_rbspy/src/lib.rs @@ -15,10 +15,12 @@ use std::{ thread::JoinHandle, }; +const LOG_TAG: &str = "Pyroscope::Rbspy"; + /// Short-hand function for creating a new Rbspy backend. pub fn rbspy_backend(config: RbspyConfig) -> BackendImpl { // Clone BackendConfig to pass to the backend object. - let backend_config = config.backend_config.clone(); + let backend_config = config.backend_config; // Create a new backend object. BackendImpl::new(Box::new(Rbspy::new(config)), Some(backend_config)) @@ -38,9 +40,9 @@ pub struct RbspyConfig { /// Profiling duration. None for infinite. time_limit: Option, /// Include subprocesses - with_subprocesses: bool, + detect_subprocesses: bool, /// Include Oncpu Time - on_cpu: bool, + oncpu: bool, } impl Default for RbspyConfig { @@ -51,8 +53,8 @@ impl Default for RbspyConfig { backend_config: BackendConfig::default(), lock_process: false, time_limit: None, - with_subprocesses: false, - on_cpu: false, + detect_subprocesses: false, + oncpu: false, } } } @@ -114,16 +116,16 @@ impl RbspyConfig { } /// Include subprocesses - pub fn with_subprocesses(self, with_subprocesses: bool) -> Self { + pub fn detect_subprocesses(self, detect_subprocesses: bool) -> Self { RbspyConfig { - with_subprocesses, + detect_subprocesses, ..self } } /// Include idle time - pub fn on_cpu(self, on_cpu: bool) -> Self { - RbspyConfig { on_cpu, ..self } + pub fn oncpu(self, oncpu: bool) -> Self { + RbspyConfig { oncpu, ..self } } } @@ -184,7 +186,7 @@ impl Backend for Rbspy { Ok(self.config.sample_rate) } - fn set_config(&self, config: BackendConfig) {} + fn set_config(&self, _config: BackendConfig) {} fn get_config(&self) -> Result { Ok(self.config.backend_config) @@ -217,9 +219,9 @@ impl Backend for Rbspy { self.config.sample_rate, self.config.lock_process, self.config.time_limit, - self.config.with_subprocesses, + self.config.detect_subprocesses, None, - self.config.on_cpu, + self.config.oncpu, )); // Channel for Errors generated by the RubySpy Sampler @@ -259,7 +261,7 @@ impl Backend for Rbspy { // ruleset reference let ruleset = self.ruleset.clone(); - let backend_config = self.config.backend_config.clone(); + let backend_config = self.config.backend_config; let _: JoinHandle> = std::thread::spawn(move || { // Iterate over the StackTrace @@ -280,6 +282,8 @@ impl Backend for Rbspy { } fn shutdown(self: Box) -> Result<()> { + log::trace!(target: LOG_TAG, "Shutting down sampler thread"); + // Stop Sampler self.sampler .as_ref() diff --git a/pyroscope_cli/CHANGELOG.md b/pyroscope_cli/CHANGELOG.md index e9d85f2f..595f69f0 100644 --- a/pyroscope_cli/CHANGELOG.md +++ b/pyroscope_cli/CHANGELOG.md @@ -1,4 +1,4 @@ -# v0.2.0 +# v0.2.1 - Update pyroscope lib to 0.5.2 - update pprof-rs backend to 0.2.1 - update rbspy backend to 0.2.1 diff --git a/pyroscope_cli/Cargo.lock b/pyroscope_cli/Cargo.lock index dec4346b..b518968f 100644 --- a/pyroscope_cli/Cargo.lock +++ b/pyroscope_cli/Cargo.lock @@ -7,11 +7,20 @@ name = "addr2line" version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +dependencies = [ + "gimli", +] + +[[package]] +name = "addr2line" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ca9b76e919fd83ccfb509f51b28c333c0e03f2221616e347a129215cec4e4a9" dependencies = [ "cpp_demangle", "fallible-iterator", "gimli", - "object 0.27.1", + "object", "rustc-demangle", "smallvec", ] @@ -53,15 +62,15 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.57" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc" +checksum = "c91f1f46651137be86f3a2b9a8359f9ab421d04d941c62b5982e1ca21113adf9" [[package]] name = "arc-swap" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5d78ce20460b82d3fa150275ed9d55e21064fc7951177baacf86a145c4a4b1f" +checksum = "983cd8b9d4b02a6dc6ffa557262eb5858a27a0038ffffe21a0f133eaa819a164" [[package]] name = "arrayvec" @@ -111,16 +120,16 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.65" +version = "0.3.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11a17d453482a265fd5f8479f2a3f405566e6ca627837aaddb85af8b1ab8ef61" +checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" dependencies = [ - "addr2line", + "addr2line 0.17.0", "cc", "cfg-if", "libc", "miniz_oxide", - "object 0.28.4", + "object", "rustc-demangle", ] @@ -182,15 +191,15 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.9.1" +version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" +checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" [[package]] name = "bytemuck" -version = "1.9.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdead85bdec19c194affaeeb670c0e41fe23de31459efd1c174d049269cf02cc" +checksum = "a5377c8865e74a160d21f29c2d40669f53286db6eab59b88540cbb12ffc8b835" [[package]] name = "byteorder" @@ -200,9 +209,9 @@ checksum = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855" [[package]] name = "bytes" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" [[package]] name = "cc" @@ -266,16 +275,16 @@ dependencies = [ [[package]] name = "clap" -version = "3.1.12" +version = "3.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c167e37342afc5f33fd87bbc870cedd020d2a6dffa05d45ccd9241fbdd146db" +checksum = "a3dbbb6653e7c55cc8595ad3e1f7be8f32aba4eb7ff7f0fd1163d4f3d137c0a9" dependencies = [ "atty", "bitflags", "clap_derive", "clap_lex", "indexmap", - "lazy_static", + "once_cell", "strsim 0.10.0", "termcolor", "terminal_size", @@ -284,18 +293,18 @@ dependencies = [ [[package]] name = "clap_complete" -version = "3.1.4" +version = "3.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da92e6facd8d73c22745a5d3cbb59bdf8e46e3235c923e516527d8e81eec14a4" +checksum = "ead064480dfc4880a10764488415a97fdd36a4cf1bb022d372f02e8faf8386e1" dependencies = [ - "clap 3.1.12", + "clap 3.2.16", ] [[package]] name = "clap_derive" -version = "3.1.7" +version = "3.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3aab4734e083b809aaf5794e14e756d1c798d2c69c7f7de7a09a2f5214993c1" +checksum = "9ba52acd3b0a5c33aeada5cdaa3267cdc7c594a98731d4268cdc1532f4264cb4" dependencies = [ "heck", "proc-macro-error", @@ -306,9 +315,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.1.1" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "189ddd3b5d32a70b35e7686054371742a937b0d99128e76dde6340210e966669" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" dependencies = [ "os_str_bytes", ] @@ -333,7 +342,7 @@ dependencies = [ "lazy_static", "nom 5.1.2", "rust-ini", - "serde 1.0.137", + "serde 1.0.141", "serde-hjson", "serde_json", "toml", @@ -342,14 +351,13 @@ dependencies = [ [[package]] name = "console" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28b32d32ca44b70c3e4acd7db1babf555fa026e385fb95f18028f88848b3c31" +checksum = "89eab4d20ce20cea182308bca13088fecea9c05f6776cf287205d41a0ed3c847" dependencies = [ "encode_unicode", "libc", "once_cell", - "regex", "terminal_size", "unicode-width", "winapi", @@ -391,9 +399,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.4" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" dependencies = [ "cfg-if", "crossbeam-utils", @@ -401,12 +409,12 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.8" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" +checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" dependencies = [ "cfg-if", - "lazy_static", + "once_cell", ] [[package]] @@ -415,7 +423,7 @@ version = "3.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b37feaa84e6861e00a1f5e5aa8da3ee56d605c9992d33e082786754828e20865" dependencies = [ - "nix 0.24.1", + "nix 0.24.2", "winapi", ] @@ -426,18 +434,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3495912c9c1ccf2e18976439f4443f3fee0fd61f424ff99fde6a66b15ecb448f" dependencies = [ "cfg-if", - "hashbrown 0.12.1", + "hashbrown", "lock_api", "parking_lot_core", ] [[package]] name = "debugid" -version = "0.7.3" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6ee87af31d84ef885378aebca32be3d682b0e0dc119d5b4860a2c5bb5046730" +checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" dependencies = [ - "uuid", + "uuid 1.1.2", ] [[package]] @@ -507,9 +515,9 @@ dependencies = [ [[package]] name = "either" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" [[package]] name = "elf" @@ -612,9 +620,9 @@ checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" [[package]] name = "fastrand" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" dependencies = [ "instant", ] @@ -737,20 +745,20 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ "cfg-if", "libc", - "wasi 0.10.0+wasi-snapshot-preview1", + "wasi 0.11.0+wasi-snapshot-preview1", ] [[package]] name = "gimli" -version = "0.26.1" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" +checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" dependencies = [ "fallible-iterator", "stable_deref_trait", @@ -775,9 +783,9 @@ dependencies = [ [[package]] name = "goblin" -version = "0.5.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c955ab4e0ad8c843ea653a3d143048b87490d9be56bd7132a435c2407846ac8f" +checksum = "91766b1121940d622933a13e20665857648681816089c9bc2075c4b75a6e4f6b" dependencies = [ "log", "plain", @@ -805,19 +813,13 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.11.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ "ahash", ] -[[package]] -name = "hashbrown" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3" - [[package]] name = "heck" version = "0.4.0" @@ -835,9 +837,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff8670570af52249509a86f5e3e18a08c60b177071826898fde8997cf5f6bfbb" +checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" dependencies = [ "bytes", "fnv", @@ -875,11 +877,11 @@ checksum = "39f357a500abcbd7c5f967c1d45c8838585b36743823b9d43488f24850534e36" dependencies = [ "backtrace", "os_type", - "serde 1.0.137", + "serde 1.0.141", "serde_derive", "termcolor", "toml", - "uuid", + "uuid 0.8.2", ] [[package]] @@ -899,9 +901,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.19" +version = "0.14.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42dc3c131584288d375f2d07f822b0cb012d8c6fb899a5b9fdb3cb7eb9b6004f" +checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" dependencies = [ "bytes", "futures-channel", @@ -960,12 +962,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.8.2" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6012d540c5baa3589337a98ce73408de9b5a25ec9fc2c6fd6be8f0d39e0ca5a" +checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" dependencies = [ "autocfg", - "hashbrown 0.11.2", + "hashbrown", ] [[package]] @@ -982,23 +984,23 @@ dependencies = [ [[package]] name = "inferno" -version = "0.11.4" +version = "0.11.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a3cb215599901c8f491666421d44ffaed08d6872b4c7ced6f425683b951271e" +checksum = "9709543bd6c25fdc748da2bed0f6855b07b7e93a203ae31332ac2101ab2f4782" dependencies = [ "ahash", "atty", - "clap 3.1.12", + "clap 3.2.16", "crossbeam-channel", "crossbeam-utils", "dashmap", "env_logger 0.9.0", "indexmap", "itoa 1.0.2", - "lazy_static", "log", "num-format", "num_cpus", + "once_cell", "quick-xml", "rgb", "str_stack", @@ -1042,9 +1044,9 @@ checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" [[package]] name = "js-sys" -version = "0.3.57" +version = "0.3.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" +checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2" dependencies = [ "wasm-bindgen", ] @@ -1092,9 +1094,9 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33a33a362ce288760ec6a508b94caaec573ae7d3bbbd91b87aa0bad4456839db" +checksum = "da83a57f3f5ba3680950aa3cbc806fc297bc0b289d42e8942ed528ace71b8145" [[package]] name = "libproc" @@ -1119,9 +1121,9 @@ dependencies = [ [[package]] name = "linked-hash-map" -version = "0.5.4" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "lock_api" @@ -1144,11 +1146,11 @@ dependencies = [ [[package]] name = "lru" -version = "0.7.6" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8015d95cb7b2ddd3c0d32ca38283ceb1eea09b4713ee380bceb942d85a244228" +checksum = "e999beba7b6e8345721bd280141ed958096a2e4abdf74f67ff4ce49b4b54e47a" dependencies = [ - "hashbrown 0.11.2", + "hashbrown", ] [[package]] @@ -1162,9 +1164,9 @@ dependencies = [ [[package]] name = "mach2" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c29a677a8db77a45ddd1370ac4fbd5187f827780000202079e28949f1a75cb1" +checksum = "6d0d1830bcd151a6fc4aea1369af235b36c1528fe976b8ff678683c9995eade8" dependencies = [ "libc", ] @@ -1199,9 +1201,9 @@ dependencies = [ [[package]] name = "memmap2" -version = "0.5.3" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057a3db23999c867821a7a59feb06a578fcb03685e983dff90daf9e7d24ac08f" +checksum = "3a79b39c93a7a5a27eeaf9a23b5ff43f1b9e0ad6b1cdd441140ae53c35613fc7" dependencies = [ "libc", ] @@ -1238,9 +1240,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799" +checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" dependencies = [ "libc", "log", @@ -1254,7 +1256,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7d66043b25d4a6cccb23619d10c19c25304b355a7dccd4a8e11423dd2382146" dependencies = [ - "clap 3.1.12", + "clap 3.2.16", "rand 0.8.5", ] @@ -1291,14 +1293,13 @@ dependencies = [ [[package]] name = "nix" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f17df307904acd05aa8e32e97bb20f2a0df1728bbc2d771ae8f9a90463441e9" +checksum = "195cdbc1741b8134346d515b3a56a1c94b0912758009cfd53f99ea0f57b065fc" dependencies = [ "bitflags", "cfg-if", "libc", - "memoffset", ] [[package]] @@ -1400,34 +1401,25 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "object" -version = "0.27.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" +checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" dependencies = [ "flate2", "memchr", ] -[[package]] -name = "object" -version = "0.28.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" +checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" [[package]] name = "openssl" -version = "0.10.40" +version = "0.10.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb81a6430ac911acb25fe5ac8f1d2af1b4ea8a4fdfda0f1ee4292af2e2d8eb0e" +checksum = "618febf65336490dfcf20b73f885f5651a0c89c64c2d4a8c3662585a70bf5bd0" dependencies = [ "bitflags", "cfg-if", @@ -1457,9 +1449,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.73" +version = "0.9.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5fd19fb3e0a8191c1e34935718976a3e70c112ab9a24af6d7cadccd9d90bc0" +checksum = "e5f9bd0c2710541a3cda73d6f9ac4f1b240de4ae261065d309dbe73d9dceb42f" dependencies = [ "autocfg", "cc", @@ -1480,9 +1472,9 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.1.0" +version = "6.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa" +checksum = "648001efe5d5c0102d8cea768e348da85d90af8ba91f0bea908f157951493cd4" [[package]] name = "os_type" @@ -1554,16 +1546,16 @@ checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" [[package]] name = "pprof" -version = "0.8.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2324292407eab69d4ace0eed1524fe612ac37c98aa22b0d868355b17fada530" +checksum = "1bba88ee898c63351101af3e60c66c5398c517681ce533eef8caff10ecf11ec1" dependencies = [ "backtrace", "cfg-if", "findshlibs", "libc", "log", - "nix 0.23.1", + "nix 0.24.2", "once_cell", "parking_lot", "smallvec", @@ -1644,9 +1636,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.39" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" +checksum = "c278e965f1d8cf32d6e0e96de3d3e79712178ae67986d9cf9151f51e95aac89b" dependencies = [ "unicode-ident", ] @@ -1695,7 +1687,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7663bd5eace848af4fcf0ffa0b273aaecfbf318819f4b8d0214a9f02f69d9940" dependencies = [ "chrono", - "clap 3.1.12", + "clap 3.2.16", "clap_complete", "console", "cpp_demangle", @@ -1715,7 +1707,7 @@ dependencies = [ "rand_distr", "regex", "remoteprocess", - "serde 1.0.137", + "serde 1.0.141", "serde_derive", "serde_json", "tempfile", @@ -1725,22 +1717,23 @@ dependencies = [ [[package]] name = "pyroscope" -version = "0.5.2" +version = "0.5.4" dependencies = [ "libc", "log", "names", "reqwest", "thiserror", + "url", ] [[package]] name = "pyroscope-cli" -version = "0.2.1" +version = "0.2.2" dependencies = [ "assert_cmd", "better-panic", - "clap 3.1.12", + "clap 3.2.16", "clap_complete", "color-backtrace", "config", @@ -1756,7 +1749,7 @@ dependencies = [ "pyroscope_pprofrs", "pyroscope_pyspy", "pyroscope_rbspy", - "serde 1.0.137", + "serde 1.0.141", "slog", "slog-async", "slog-scope", @@ -1767,8 +1760,9 @@ dependencies = [ [[package]] name = "pyroscope_pprofrs" -version = "0.2.1" +version = "0.2.4" dependencies = [ + "log", "pprof", "pyroscope", "thiserror", @@ -1776,7 +1770,7 @@ dependencies = [ [[package]] name = "pyroscope_pyspy" -version = "0.2.1" +version = "0.2.4" dependencies = [ "log", "py-spy", @@ -1786,12 +1780,12 @@ dependencies = [ [[package]] name = "pyroscope_rbspy" -version = "0.2.1" +version = "0.2.3" dependencies = [ "anyhow", "log", "pyroscope", - "rbspy", + "rbspy-oncpu", "thiserror", ] @@ -1812,9 +1806,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.18" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" dependencies = [ "proc-macro2", ] @@ -1888,14 +1882,14 @@ dependencies = [ ] [[package]] -name = "rbspy" +name = "rbspy-oncpu" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcbebdf0037de5a92722b0bca2965ce0a76cd5c962225cf355e31ac668ea653f" +checksum = "fdc6110000bf4e0c644e1ba4e86877cc84da7a637e3fa394cecedcaf9728870c" dependencies = [ "anyhow", "chrono", - "clap 3.1.12", + "clap 3.2.16", "ctrlc", "directories", "elf", @@ -1911,7 +1905,7 @@ dependencies = [ "rand 0.8.5", "rbspy-ruby-structs", "remoteprocess", - "serde 1.0.137", + "serde 1.0.141", "serde_derive", "serde_json", "tempdir", @@ -1949,9 +1943,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.13" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ "bitflags", ] @@ -1969,9 +1963,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.5.6" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1" +checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" dependencies = [ "aho-corasick", "memchr", @@ -1986,18 +1980,18 @@ checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" [[package]] name = "regex-syntax" -version = "0.6.26" +version = "0.6.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" +checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" [[package]] name = "remoteprocess" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9f13e22b81d40176f4d7ed41c029fd2c7306b182db9838a44d88aeb97a7c6d6" +checksum = "ab91eb6b1c4c507a08d6fb6e2f38982a1e09923d19023506cba25aefcfc6e46f" dependencies = [ - "addr2line", - "goblin 0.5.1", + "addr2line 0.18.0", + "goblin 0.5.3", "lazy_static", "libc", "libproc 0.12.0", @@ -2005,8 +1999,8 @@ dependencies = [ "mach", "mach_o_sys", "memmap", - "nix 0.24.1", - "object 0.27.1", + "nix 0.24.2", + "object", "proc-maps", "read-process-memory", "regex", @@ -2024,9 +2018,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.10" +version = "0.11.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46a1f7aa4f35e5e8b4160449f51afc758f0ce6454315a9fa7d0d113e958c41eb" +checksum = "b75aa69a3f06bbcc66ede33af2af253c6f7a86b1ca0033f60c580a27074fbf92" dependencies = [ "base64", "bytes", @@ -2049,13 +2043,14 @@ dependencies = [ "pin-project-lite", "rustls", "rustls-native-certs", - "rustls-pemfile 0.3.0", - "serde 1.0.137", + "rustls-pemfile", + "serde 1.0.141", "serde_json", "serde_urlencoded", "tokio", "tokio-native-tls", "tokio-rustls", + "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", @@ -2065,9 +2060,9 @@ dependencies = [ [[package]] name = "rgb" -version = "0.8.32" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e74fdc210d8f24a7dbfedc13b04ba5764f5232754ccebfdf5fff1bad791ccbc6" +checksum = "c3b221de559e4a29df3b957eec92bc0de6bc8eaf6ca9cfed43e5e1d67ff65a34" dependencies = [ "bytemuck", ] @@ -2124,20 +2119,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0167bac7a9f490495f3c33013e7722b53cb087ecbe082fb0c6387c96f634ea50" dependencies = [ "openssl-probe", - "rustls-pemfile 1.0.0", + "rustls-pemfile", "schannel", "security-framework", ] -[[package]] -name = "rustls-pemfile" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee86d63972a7c661d1536fefe8c3c8407321c3df668891286de28abcd087360" -dependencies = [ - "base64", -] - [[package]] name = "rustls-pemfile" version = "1.0.0" @@ -2149,9 +2135,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" +checksum = "24c8ad4f0c00e1eb5bc7614d236a7f1300e3dbd76b68cac8e06fb00b015ad8d8" [[package]] name = "ryu" @@ -2256,9 +2242,9 @@ checksum = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8" [[package]] name = "serde" -version = "1.0.137" +version = "1.0.141" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" +checksum = "7af873f2c95b99fcb0bd0fe622a43e29514658873c8ceba88c4cb88833a22500" dependencies = [ "serde_derive", ] @@ -2277,9 +2263,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.137" +version = "1.0.141" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" +checksum = "75743a150d003dd863b51dc809bcad0d73f2102c53632f1e954e738192a3413f" dependencies = [ "proc-macro2", "quote", @@ -2288,13 +2274,13 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" +checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7" dependencies = [ "itoa 1.0.2", "ryu", - "serde 1.0.137", + "serde 1.0.141", ] [[package]] @@ -2306,7 +2292,7 @@ dependencies = [ "form_urlencoded", "itoa 1.0.2", "ryu", - "serde 1.0.137", + "serde 1.0.141", ] [[package]] @@ -2327,9 +2313,12 @@ checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" [[package]] name = "slab" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +dependencies = [ + "autocfg", +] [[package]] name = "slog" @@ -2381,14 +2370,14 @@ dependencies = [ "slog", "term", "thread_local", - "time 0.3.9", + "time 0.3.12", ] [[package]] name = "smallvec" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" +checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" [[package]] name = "socket2" @@ -2438,21 +2427,21 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "symbolic-common" -version = "8.7.3" +version = "9.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c276d5b296f30f0fb30d2128b6be6f9804be7669f1edef46c4d8c017de4c77c3" +checksum = "9ea2ab8b85d27d49d184438b4b77fbd521b385cc9c5c802f60e784f2df25a03d" dependencies = [ "debugid", "memmap2", "stable_deref_trait", - "uuid", + "uuid 1.1.2", ] [[package]] name = "symbolic-demangle" -version = "8.7.3" +version = "9.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b096bd4794e4d05584144dc9536a4fde8844da73f84cdb7652ed78b59e37a218" +checksum = "7939b15a1c62633d1fce17f8a7b668312eaa2d3b117bf4ced5e6e77870c43b6a" dependencies = [ "cpp_demangle", "rustc-demangle", @@ -2461,9 +2450,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.95" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942" +checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" dependencies = [ "proc-macro2", "quote", @@ -2627,11 +2616,12 @@ dependencies = [ [[package]] name = "time" -version = "0.3.9" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2702e08a7a860f005826c6815dcac101b19b5eb330c27fe4a5928fec1d20ddd" +checksum = "74b7cc93fc23ba97fde84f7eea56c55d1ba183f495c6715defdfc7b9cb8c870f" dependencies = [ "itoa 1.0.2", + "js-sys", "libc", "num_threads", "time-macros", @@ -2660,10 +2650,11 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.18.2" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4903bf0427cf68dddd5aa6a93220756f8be0c34fcfa9f5e6191e103e15a31395" +checksum = "7a8325f63a7d4774dd041e363b2409ed1c5cbbd0f867795e661df066b2b0a581" dependencies = [ + "autocfg", "bytes", "libc", "memchr", @@ -2698,9 +2689,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f988a1a1adc2fb21f9c12aa96441da33a1728193ae0b95d2be22dbd17fcb4e5c" +checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" dependencies = [ "bytes", "futures-core", @@ -2716,45 +2707,33 @@ version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" dependencies = [ - "serde 1.0.137", + "serde 1.0.141", ] [[package]] name = "tower-service" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.34" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09" +checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" dependencies = [ "cfg-if", "pin-project-lite", - "tracing-attributes", "tracing-core", ] -[[package]] -name = "tracing-attributes" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "tracing-core" -version = "0.1.26" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f" +checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" dependencies = [ - "lazy_static", + "once_cell", ] [[package]] @@ -2771,15 +2750,15 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-ident" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" +checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7" [[package]] name = "unicode-normalization" -version = "0.1.19" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6" dependencies = [ "tinyvec", ] @@ -2823,6 +2802,12 @@ dependencies = [ "getrandom", ] +[[package]] +name = "uuid" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd6469f4314d5f1ffec476e05f17cc9a78bc7a27a6a857842170bdf8d6f98d2f" + [[package]] name = "vcpkg" version = "0.2.15" @@ -2874,9 +2859,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.80" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" +checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -2884,13 +2869,13 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.80" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4" +checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f" dependencies = [ "bumpalo", - "lazy_static", "log", + "once_cell", "proc-macro2", "quote", "syn", @@ -2899,9 +2884,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.30" +version = "0.4.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f741de44b75e14c35df886aff5f1eb73aa114fa5d4d00dcd37b5e01259bf3b2" +checksum = "fa76fb221a1f8acddf5b54ace85912606980ad661ac7a503b4570ffd3a624dad" dependencies = [ "cfg-if", "js-sys", @@ -2911,9 +2896,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.80" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" +checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2921,9 +2906,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.80" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" +checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da" dependencies = [ "proc-macro2", "quote", @@ -2934,15 +2919,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.80" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" +checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a" [[package]] name = "web-sys" -version = "0.3.57" +version = "0.3.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283" +checksum = "ed055ab27f941423197eb86b2035720b1a3ce40504df082cac2ecc6ed73335a1" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/pyroscope_cli/Cargo.toml b/pyroscope_cli/Cargo.toml index 2779e16f..d4216efb 100644 --- a/pyroscope_cli/Cargo.toml +++ b/pyroscope_cli/Cargo.toml @@ -5,7 +5,7 @@ Pyroscope Profiler CLI """ keywords = ["pyroscope", "profiler", "cli"] authors = ["Abid Omar "] -version = "0.2.1" +version = "0.2.2" edition = "2021" license = "Apache-2.0" homepage = "https://pyroscope.io" @@ -19,7 +19,7 @@ human-panic = "1.0.3" pretty_env_logger = "0.4.0" better-panic = "0.3.0" log = "=0.4.16" -clap_complete = "3.1" +clap_complete = "3.2" names= "0.13.0" ctrlc = "3.2.2" duct = "0.13.5" @@ -33,13 +33,13 @@ slog-term = "2.8.0" slog-scope = "4.4.0" slog-async = "2.7.0" slog-stdlog = "4.1.0" -pyroscope = { version = "0.5.2", path = "../" } -pyroscope_pprofrs = {version = "0.2.1", path = "../pyroscope_backends/pyroscope_pprofrs" } -pyroscope_rbspy = {version = "0.2.1", path = "../pyroscope_backends/pyroscope_rbspy" } -pyroscope_pyspy = {version = "0.2.1", path = "../pyroscope_backends/pyroscope_pyspy" } +pyroscope = { version = "0.5.4", path = "../" } +pyroscope_pprofrs = {version = "0.2.3", path = "../pyroscope_backends/pyroscope_pprofrs" } +pyroscope_rbspy = {version = "0.2.2", path = "../pyroscope_backends/pyroscope_rbspy" } +pyroscope_pyspy = {version = "0.2.3", path = "../pyroscope_backends/pyroscope_pyspy" } [dependencies.clap] -version = "=3.1.12" +version = "3.2" features = ["cargo", "derive"] [dev-dependencies] diff --git a/pyroscope_cli/src/cli/lib.rs b/pyroscope_cli/src/cli/lib.rs index 9c378628..b1c6ea6f 100644 --- a/pyroscope_cli/src/cli/lib.rs +++ b/pyroscope_cli/src/cli/lib.rs @@ -57,6 +57,13 @@ enum Commands { help = "application name used when uploading profiling data" )] application_name: Option, + #[clap( + name = "auth_token", + long = "auth-token", + value_name = "AUTH_TOKEN", + help = "Authentication token used when uploading profiling data" + )] + auth_token: Option, #[clap( name = "detect_subprocesses", long = "detect-subprocesses", @@ -91,10 +98,10 @@ enum Commands { )] blocking: bool, #[clap( - name = "pyspy_idle", - long = "pyspy-idle", - value_name = "PYSPY_IDLE", - help = "include idle threads for pyspy", + name = "oncpu", + long = "oncpu", + value_name = "ONCPU", + help = "enable oncpu mode. [supported by: rbspy, pyspy]", takes_value = false )] pyspy_idle: bool, @@ -168,6 +175,13 @@ enum Commands { help = "application name used when uploading profiling data" )] application_name: Option, + #[clap( + name = "auth_token", + long = "auth-token", + value_name = "AUTH_TOKEN", + help = "Authentication token used when uploading profiling data" + )] + auth_token: Option, #[clap( name = "detect_subprocesses", long = "detect-subprocesses", @@ -194,10 +208,10 @@ enum Commands { )] blocking: bool, #[clap( - name = "pyspy_idle", - long = "pyspy-idle", - value_name = "PYSPY_IDLE", - help = "include idle threads for pyspy", + name = "oncpu", + long = "oncpu", + value_name = "ONCPU", + help = "enable oncpu mode. [supported by: rbspy, pyspy]", takes_value = false )] pyspy_idle: bool, diff --git a/pyroscope_cli/src/core/profiler.rs b/pyroscope_cli/src/core/profiler.rs index 629cd5d0..3686b453 100644 --- a/pyroscope_cli/src/core/profiler.rs +++ b/pyroscope_cli/src/core/profiler.rs @@ -21,13 +21,15 @@ impl Profiler { let app_name: String = AppConfig::get::("application_name")?; + let auth_token: String = AppConfig::get::("auth_token")?; + let server_address: String = AppConfig::get::("server_address")?; let sample_rate: u32 = AppConfig::get::("sample_rate")?; let blocking: bool = AppConfig::get::("blocking")?; - let pyspy_idle: bool = AppConfig::get::("pyspy_idle")?; + let oncpu: bool = AppConfig::get::("oncpu")?; let pyspy_gil: bool = AppConfig::get::("pyspy_gil")?; let pyspy_native: bool = AppConfig::get::("pyspy_native")?; @@ -41,26 +43,42 @@ impl Profiler { let config = PyspyConfig::new(pid) .sample_rate(sample_rate) .lock_process(blocking) - .with_subprocesses(detect_subprocesses) - .include_idle(pyspy_idle) + .detect_subprocesses(detect_subprocesses) + .oncpu(oncpu) .gil_only(pyspy_gil) .native(pyspy_native); + let backend = pyspy_backend(config); - PyroscopeAgent::builder(server_address, app_name) - .backend(backend) - .tags(tags) - .build()? + + let mut builder = PyroscopeAgent::default_builder(); + builder = builder.url(server_address); + builder = builder.application_name(app_name); + + // There must be a better way to do this, hopefully as clap supports Option + if auth_token.len() > 0 { + builder = builder.auth_token(auth_token); + } + + builder.backend(backend).tags(tags).build()? } Spy::Rbspy => { let config = RbspyConfig::new(pid) .sample_rate(sample_rate) .lock_process(blocking) - .with_subprocesses(detect_subprocesses); + .oncpu(oncpu) + .detect_subprocesses(detect_subprocesses); let backend = rbspy_backend(config); - PyroscopeAgent::builder(server_address, app_name) - .backend(backend) - .tags(tags) - .build()? + + let mut builder = PyroscopeAgent::default_builder(); + builder = builder.url(server_address); + builder = builder.application_name(app_name); + + // There must be a better way to do this, hopefully as clap supports Option + if auth_token.len() > 0 { + builder = builder.auth_token(auth_token); + } + + builder.backend(backend).tags(tags).build()? } }; diff --git a/pyroscope_cli/src/resources/default_config.toml b/pyroscope_cli/src/resources/default_config.toml index 7fa7927f..d2246b3e 100644 --- a/pyroscope_cli/src/resources/default_config.toml +++ b/pyroscope_cli/src/resources/default_config.toml @@ -2,9 +2,10 @@ detect_subprocesses = false log_level = "info" no_logging = false blocking = false -pyspy_idle = false +oncpu = false pyspy_gil = false pyspy_native = false sample_rate = 100 server_address = "http://localhost:4040" +auth_token = "" debug = false diff --git a/pyroscope_cli/src/utils/app_config.rs b/pyroscope_cli/src/utils/app_config.rs index 24e806a8..ffb0a53a 100644 --- a/pyroscope_cli/src/utils/app_config.rs +++ b/pyroscope_cli/src/utils/app_config.rs @@ -19,12 +19,13 @@ pub struct AppConfig { pub pid: Option, pub spy_name: Spy, pub application_name: Option, + pub auth_token: Option, pub detect_subprocesses: Option, pub no_logging: Option, pub log_level: LogLevel, pub no_root_drop: Option, pub blocking: Option, - pub pyspy_idle: Option, + pub onpcu: Option, pub pyspy_gil: Option, pub pyspy_native: Option, pub sample_rate: Option, @@ -77,8 +78,8 @@ impl AppConfig { if sub_connect.is_present("blocking") { AppConfig::set("blocking", "true")?; } - if sub_connect.is_present("pyspy_idle") { - AppConfig::set("pyspy_idle", "true")?; + if sub_connect.is_present("oncpu") { + AppConfig::set("oncpu", "true")?; } if sub_connect.is_present("pyspy_gil") { AppConfig::set("pyspy_gil", "true")?; @@ -109,6 +110,11 @@ impl AppConfig { AppConfig::set("application_name", application_name)?; } } + if sub_connect.is_present("auth_token") { + if let Some(auth_token) = sub_connect.value_of("auth_token") { + AppConfig::set("auth_token", auth_token)?; + } + } if sub_connect.is_present("detect_subprocesses") { AppConfig::set("detect_subprocesses", "true")?; } @@ -157,8 +163,8 @@ impl AppConfig { if sub_exec.is_present("blocking") { AppConfig::set("blocking", "true")?; } - if sub_exec.is_present("pyspy_idle") { - AppConfig::set("pyspy_idle", "true")?; + if sub_exec.is_present("oncpu") { + AppConfig::set("oncpu", "true")?; } if sub_exec.is_present("pyspy_gil") { AppConfig::set("pyspy_gil", "true")?; @@ -189,6 +195,11 @@ impl AppConfig { AppConfig::set("application_name", application_name)?; } } + if sub_exec.is_present("auth_token") { + if let Some(auth_token) = sub_exec.value_of("auth_token") { + AppConfig::set("auth_token", auth_token)?; + } + } if sub_exec.is_present("detect_subprocesses") { AppConfig::set("detect_subprocesses", "true")?; } diff --git a/pyroscope_ffi/python/README.md b/pyroscope_ffi/python/README.md index 9a4ba39f..b5246199 100644 --- a/pyroscope_ffi/python/README.md +++ b/pyroscope_ffi/python/README.md @@ -1,4 +1,15 @@ -# Pyroscope Python Integration +# Pyroscope Python Package + +**Pyroscope integration for Python** + +[![license](https://img.shields.io/badge/license-Apache2.0-blue.svg)](LICENSE) +![tests](https://github.com/pyroscope-io/pyroscope-rs/workflows/Tests/badge.svg) +![build](https://github.com/pyroscope-io/pyroscope-rs/workflows/Build/badge.svg) +[![PyPI version](https://badge.fury.io/py/pyroscope-io.svg)](https://badge.fury.io/py/pyroscope-io) +[![PyPI](https://img.shields.io/pypi/pyversions/pyroscope-io.svg?maxAge=2592000)](https://pypi.python.org/pypi/pyroscope-io) + + +--- ### What is Pyroscope [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. @@ -9,37 +20,53 @@ pip install pyroscope-io ``` -### Basic Usage of Pyroscope -``` -import pyroscope_io as pyroscope +### Minimal Configuration + +Add the following code to your application. This code will initialize pyroscope profiler and start profiling: + +```python +import pyroscope pyroscope.configure( - application_name = "my.python.app", # replace this with some name for your application - server_address = "http://my-pyroscope-server:4040", # replace this with the address of your pyroscope server + application_name = "my.python.app", # replace this with some name for your application + server_address = "http://my-pyroscope-server:4040", # replace this with the address of your pyroscope server ) ``` -### Adding Tags -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. +### Full Configuration -``` -import os +Optionally, you can configure several parameters: + +```python import pyroscope pyroscope.configure( - application_name = "simple.python.app", - server_address = "http://my-pyroscope-server:4040", - - tags = { - "hostname": os.getenv("HOSTNAME"), + application_name = "my.python.app", # replace this with some name for your application + server_address = "http://my-pyroscope-server:4040", # replace this with the address of your pyroscope server + auth_token = "{YOUR_API_KEY}", # optional, if authentication is enabled, specify the API key + sample_rate = 100, # default is 100 + detect_subprocesses = False, # detect subprocesses started by the main process; default is False + oncpu = True # report cpu time only; default is True + native = False # profile native extensions; default is False + gil_only = True # only include traces for threads that are holding on to the Global Interpreter Lock; default is True + log_level = "info" # default is info, possible values: trace, debug, info, warn, error and critical + tags = { + "region": '{os.getenv("REGION")}', } ) +``` + +### Tags + +You can add tags to certain parts of your code: + +```python # You can use a wrapper: with pyroscope.tag_wrapper({ "controller": "slow_controller_i_want_to_profile" }): slow_code() ``` +### Example -### Examples -For more examples see [examples/python](https://github.com/pyroscope-io/pyroscope/tree/main/examples/python) in the main repo. +Check out this [example python project in our repository](https://github.com/pyroscope-io/pyroscope/tree/main/examples/python) for examples of how you can use these features. diff --git a/pyroscope_ffi/python/lib/src/lib.rs b/pyroscope_ffi/python/lib/src/lib.rs index 405c0c54..478e07a9 100644 --- a/pyroscope_ffi/python/lib/src/lib.rs +++ b/pyroscope_ffi/python/lib/src/lib.rs @@ -75,8 +75,8 @@ pub extern "C" fn initialize_agent( let mut pyspy_config = PyspyConfig::new(pid.try_into().unwrap()) .sample_rate(sample_rate) .lock_process(false) - .with_subprocesses(detect_subprocesses) - .include_idle(!oncpu) + .detect_subprocesses(detect_subprocesses) + .oncpu(oncpu) .native(native) .gil_only(gil_only); diff --git a/pyroscope_ffi/python/pyroscope/__init__.py b/pyroscope_ffi/python/pyroscope/__init__.py index b378d16a..62fbe40d 100644 --- a/pyroscope_ffi/python/pyroscope/__init__.py +++ b/pyroscope_ffi/python/pyroscope/__init__.py @@ -6,10 +6,11 @@ from contextlib import contextmanager -Config = namedtuple('Config', ('app_name', 'application_name', 'server_address', 'auth_token', 'sample_rate', 'detect_subprocesses','oncpu', 'native', 'gil_only')) +Config = namedtuple('Config', ('app_name', 'application_name', + 'server_address', 'auth_token', 'enable_logging', 'sample_rate', 'detect_subprocesses','oncpu', 'native', 'gil_only')) def configure(app_name=None, application_name=None, server_address="http://localhost:4040", - auth_token = "", sample_rate=100, detect_subprocesses=False, + auth_token="", enable_logging=False, sample_rate=100, detect_subprocesses=False, oncpu=True, native=False, gil_only=True, report_pid=False, report_thread_id=False, report_thread_name=False, tags=None): @@ -26,9 +27,10 @@ def configure(app_name=None, application_name=None, server_address="http://local # INFO = 20 # DEBUG = 10 # NOTSET = 0 - logger = logging.getLogger() - log_level = logger.getEffectiveLevel() - lib.initialize_logging(log_level) + if enable_logging: + logger = logging.getLogger() + log_level = logger.getEffectiveLevel() + lib.initialize_logging(log_level) # Initialize Pyroscope Agent lib.initialize_agent(application_name.encode("UTF-8"), diff --git a/pyroscope_ffi/python/scripts/tests/test.py b/pyroscope_ffi/python/scripts/tests/test.py new file mode 100755 index 00000000..d57d3b05 --- /dev/null +++ b/pyroscope_ffi/python/scripts/tests/test.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +import hashlib +import os +import threading +import logging + +import pyroscope + + +# Set python logging level to DEBUG +logger = logging.getLogger() +logger.setLevel(logging.DEBUG) + +# Configure Pyroscope +pyroscope.configure( + application_name = f'{os.getenv("PYROSCOPE_RUN_ID")}', + server_address = "https://ingest.pyroscope.cloud", + auth_token = f'{os.getenv("PYROSCOPE_API_TOKEN")}', + enable_logging =True, + detect_subprocesses = os.getenv("PYROSCOPE_DETECT_SUBPROCESSES") == "true", + oncpu = os.getenv("PYROSCOPE_ONCPU") == "true", + gil_only = os.getenv("PYROSCOPE_GIL_ONLY") == "true", + report_pid = True, + report_thread_id = True, + report_thread_name = True, + tags = { + "detect_subprocesses": f'{os.getenv("PYROSCOPE_DETECT_SUBPROCESSES")}', + "oncpu": f'{os.getenv("PYROSCOPE_ONCPU")}', + "gil_only": f'{os.getenv("PYROSCOPE_GIL_ONLY")}', + "version": f'{os.getenv("PYTHON_VERSION")}', + "arch": f'{os.getenv("PYROSCOPE_ARCH")}', + } +) + + +def hash(string): + string = string.encode() + string = hashlib.sha256(string).hexdigest() + + return string + +def multihash(string): + for i in range(0, 25510055): + string = hash(string) + return string + +def multihash2(string): + for i in range(0, 25510055): + string = hash(string) + return string + +thread_1 = threading.Thread(target=multihash, args=('abc',)) +thread_2 = threading.Thread(target=multihash2, args=('abc',)) + +thread_1.start() +thread_2.start() + +thread_1.join() +thread_2.join() + +pyroscope.shutdown() diff --git a/pyroscope_ffi/ruby/README.md b/pyroscope_ffi/ruby/README.md index 53f87732..12ad1de3 100644 --- a/pyroscope_ffi/ruby/README.md +++ b/pyroscope_ffi/ruby/README.md @@ -1,57 +1,71 @@ -Pyroscope Ruby Integration --Beta-- -===================================== +# Pyroscope Ruby Gem -**note**: This is a beta release. It requires local compilation, might be -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). +**Pyroscope integration for Ruby** -## Installation +[![license](https://img.shields.io/badge/license-Apache2.0-blue.svg)](LICENSE) +![tests](https://github.com/pyroscope-io/pyroscope-rs/workflows/Tests/badge.svg) +![build](https://github.com/pyroscope-io/pyroscope-rs/workflows/Build/badge.svg) +[![Gem version](https://badge.fury.io/rb/pyroscope.svg)](https://badge.fury.io/rb/pyroscope) -1. You need the Rust toolchain to compile the library locally. To install - Rust: +--- -``` -curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain stable -y -export PATH=$PATH:/root/.cargo/bin -``` +### What is Pyroscope +[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. -2. Building/Insalling from Rubygems -``` -gem install pyroscope_beta -``` +### Supported platforms -3. Building/Installing from source +| Linux | macOS | Windows | Docker | +|:-----:|:-----:|:-------:|:------:| +| ✅ | ✅ | | ✅ | -Change directory to `pyroscope_ffi/ruby` and run +### Profiling Ruby applications +Add the `pyroscope` gem to your Gemfile: + +```bash +bundle add pyroscope ``` -gem build pyroscope.gemspec -gem install ./pyroscope.gemspec -``` -## Configuration +### Basic Configuration + +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: -Configuration is similar to the old package except for `application_name`: +```ruby +require 'pyroscope' +Pyroscope.configure do |config| + config.application_name = "my.ruby.app" # replace this with some name for your application + config.server_address = "http://my-pyroscope-server:4040" # replace this with the address of your pyroscope server + # config.auth_token = "{YOUR_API_KEY}" # optionally, if authentication is enabled, specify the API key +end ``` -require 'pyroscope_beta' + +### Tags + +Pyroscope ruby integration provides a number of ways to tag profiling data. For example, you can provide tags when you're initializing the profiler: + +```ruby +require 'pyroscope' Pyroscope.configure do |config| - config.application_name = "ruby.app" - config.server_address = "http://localhost:4040" - config.detect_subprocesses = true + config.application_name = "my.ruby.app" + config.server_address = "http://my-pyroscope-server:4040" + config.tags = { - :key => "value", + "hostname" => ENV["HOSTNAME"], } end ``` -## Adding tags +or you can dynamically tag certain parts of your code: -Tags passed to configure are global. To tag code locally, you can use: - -``` -Pyroscope.tag_wrapper({"profile": "profile-1"}) do - // Tagged profile +```ruby +Pyroscope.tag_wrapper({ "controller": "slow_controller_i_want_to_profile" }) do + slow_code end ``` + +### Example + +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. diff --git a/pyroscope_ffi/ruby/ext/rbspy/src/lib.rs b/pyroscope_ffi/ruby/ext/rbspy/src/lib.rs index b4faabb2..f92caec5 100644 --- a/pyroscope_ffi/ruby/ext/rbspy/src/lib.rs +++ b/pyroscope_ffi/ruby/ext/rbspy/src/lib.rs @@ -1,16 +1,109 @@ use ffikit::Signal; -use pyroscope::backend::Tag; +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; +pub fn transform_report(report: Report) -> Report { + let cwd = env::current_dir().unwrap(); + let cwd = cwd.to_str().unwrap_or(""); + + let data = report + .data + .iter() + .map(|(stacktrace, count)| { + let new_frames = stacktrace + .frames + .iter() + .map(|frame| { + let frame = frame.to_owned(); + let mut s = frame.filename.unwrap(); + match s.find(cwd) { + Some(i) => { + s = s[(i + cwd.len() + 1)..].to_string(); + } + None => match s.find("/gems/") { + Some(i) => { + s = s[(i + 1)..].to_string(); + } + None => match s.find("/ruby/") { + Some(i) => { + s = s[(i + 6)..].to_string(); + match s.find("/") { + Some(i) => { + s = s[(i + 1)..].to_string(); + } + None => {} + } + } + None => {} + }, + }, + } + + // something + StackFrame::new( + frame.module, + frame.name, + Some(s.to_string()), + frame.relative_path, + frame.absolute_path, + frame.line, + ) + }) + .collect(); + + let mut mystack = stacktrace.to_owned(); + + mystack.frames = new_frames; + + (mystack, count.to_owned()) + }) + .collect(); + + let new_report = Report::new(data).metadata(report.metadata.clone()); + + new_report +} + +#[no_mangle] +pub extern "C" fn initialize_logging(logging_level: u32) -> bool { + // Force rustc to display the log messages in the console. + match logging_level { + 50 => { + std::env::set_var("RUST_LOG", "error"); + } + 40 => { + std::env::set_var("RUST_LOG", "warn"); + } + 30 => { + std::env::set_var("RUST_LOG", "info"); + } + 20 => { + std::env::set_var("RUST_LOG", "debug"); + } + 10 => { + std::env::set_var("RUST_LOG", "trace"); + } + _ => { + std::env::set_var("RUST_LOG", "debug"); + } + } + + // Initialize the logger. + pretty_env_logger::init_timed(); + + true +} + #[no_mangle] 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, on_cpu: bool, report_pid: bool, + sample_rate: u32, detect_subprocesses: bool, oncpu: bool, report_pid: bool, report_thread_id: bool, tags: *const c_char, ) -> bool { // Initialize FFIKit @@ -41,8 +134,8 @@ pub extern "C" fn initialize_agent( let rbspy_config = RbspyConfig::new(pid.try_into().unwrap()) .sample_rate(sample_rate) .lock_process(false) - .with_subprocesses(detect_subprocesses) - .on_cpu(on_cpu) + .detect_subprocesses(detect_subprocesses) + .oncpu(oncpu) .report_pid(report_pid) .report_thread_id(report_thread_id); @@ -52,6 +145,7 @@ pub extern "C" fn initialize_agent( let mut agent_builder = PyroscopeAgent::builder(server_address, application_name) .backend(rbspy) + .func(transform_report) .tags(tags); if auth_token != "" { diff --git a/pyroscope_ffi/ruby/lib/pyroscope.rb b/pyroscope_ffi/ruby/lib/pyroscope.rb index 11929703..a43a8eb9 100644 --- a/pyroscope_ffi/ruby/lib/pyroscope.rb +++ b/pyroscope_ffi/ruby/lib/pyroscope.rb @@ -1,9 +1,13 @@ +# coding: utf-8 +# frozen_string_literal: true + require 'ffi' module Pyroscope 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 :add_thread_tag, [:uint64, :string, :string], :bool attach_function :remove_thread_tag, [:uint64, :string, :string], :bool @@ -18,17 +22,17 @@ module Utils attach_function :thread_id, [], :uint64 end - 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 + 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 def initialize(*) self.application_name = '' self.server_address = 'http://localhost:4040' self.auth_token = '' self.sample_rate = 100 self.detect_subprocesses = false - self.on_cpu = true + self.oncpu = true self.report_pid = false self.report_thread_id = false - self.log_level = 'info' + self.log_level = 'error' self.tags = {} super end @@ -41,13 +45,34 @@ def configure # Pass config to the block yield @config + # Determine Logging level (kinda like an enum). + case @config.log_level + when 'trace' + @log_level = 10 + when 'debug' + @log_level = 20 + when 'info' + @log_level = 30 + when 'warn' + @log_level = 40 + when 'error' + @log_level = 50 + else + @log_level = 50 + end + + # Initialize Logging + Rust.initialize_logging(@log_level) + + + # initialize Pyroscope Agent Rust.initialize_agent( @config.app_name || @config.application_name || "", @config.server_address || "", @config.auth_token || "", @config.sample_rate || 100, @config.detect_subprocesses || false, - @config.on_cpu || false, + @config.oncpu || false, @config.report_pid || false, @config.report_thread_id || false, tags_to_string(@config.tags || {}) @@ -96,7 +121,7 @@ def _remove_tags(thread_id, tags) end end - def drop + def shutdown Rust.drop_agent end end diff --git a/pyroscope_ffi/ruby/lib/pyroscope/version.rb b/pyroscope_ffi/ruby/lib/pyroscope/version.rb index 45cde9a1..445cf038 100644 --- a/pyroscope_ffi/ruby/lib/pyroscope/version.rb +++ b/pyroscope_ffi/ruby/lib/pyroscope/version.rb @@ -1,3 +1,3 @@ module Pyroscope - VERSION = '0.3.1'.freeze + VERSION = '0.3.2'.freeze end diff --git a/pyroscope_ffi/ruby/pyroscope.gemspec b/pyroscope_ffi/ruby/pyroscope.gemspec index 8b480326..2cfebb9b 100644 --- a/pyroscope_ffi/ruby/pyroscope.gemspec +++ b/pyroscope_ffi/ruby/pyroscope.gemspec @@ -1,4 +1,11 @@ -require_relative "lib/pyroscope/version" +# coding: utf-8 +# frozen_string_literal: true + +begin + require File.expand_path(File.join(File.dirname(__FILE__), "lib/pyroscope/version")) +rescue LoadError + puts "WARNING: Could not load Pyroscope::VERSION" +end Gem::Specification.new do |s| s.name = 'pyroscope' @@ -9,6 +16,13 @@ Gem::Specification.new do |s| s.email = ['contact@pyroscope.io'] s.homepage = 'https://pyroscope.io' s.license = 'Apache-2.0' + s.metadata = { + "homepage_uri" => "https://pyroscope.io", + "bug_tracker_uri" => "https://github.com/pyroscope-io/pyroscope-rs/issues", + "documentation_uri" => "https://pyroscope.io/docs/ruby/", + "changelog_uri" => "https://github.com/pyroscope-io/pyroscope-rs/tree/main/pyroscope_ffi/ruby/CHANGELOG.md", + "source_code_uri" => "https://github.com/pyroscope-io/pyroscope-rs/tree/main/pyroscope_ffi/ruby", + } # Specify which files should be added to the gem when it is released. # 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| s.platform = Gem::Platform::RUBY - s.required_ruby_version = ">= 2.5.9" + s.required_ruby_version = ">= 1.9.3" s.extensions = ['ext/rbspy/extconf.rb', 'ext/thread_id/extconf.rb'] diff --git a/pyroscope_ffi/ruby/scripts/tests/test.rb b/pyroscope_ffi/ruby/scripts/tests/test.rb new file mode 100755 index 00000000..33e9a466 --- /dev/null +++ b/pyroscope_ffi/ruby/scripts/tests/test.rb @@ -0,0 +1,59 @@ +#!/usr/bin/env ruby + +require "pyroscope" +require "pyroscope/version" + +puts Pyroscope::VERSION +puts RUBY_VERSION + +Pyroscope.configure do |config| + config.application_name = "#{ENV["PYROSCOPE_RUN_ID"]}" + config.server_address = "https://ingest.pyroscope.cloud" + config.auth_token = ENV["PYROSCOPE_API_TOKEN"] + config.detect_subprocesses = ENV["PYROSCOPE_DETECT_SUBPROCESSES"] == "1" + config.oncpu = ENV["PYROSCOPE_ONCPU"] == "1" + config.log_level = "trace" + config.report_pid = true + config.report_thread_id = true + config.tags = { + :region => "us-east", + :detect_subprocesses => ENV["PYROSCOPE_DETECT_SUBPROCESSES"], + :oncpu => ENV["PYROSCOPE_ONCPU"], + :version => ENV["RUBY_VERSION"], + :arch => ENV["PYROSCOPE_ARCH"] + } +end + +def work(n) + i = 0 + while i < n + i += 1 + end +end + +def fast_function + Pyroscope.tag_wrapper({"function": "fast"}) do + work(2001002000) + end +end + +def slow_function + work(8001008000) +end + +child_pid = fork do + puts "This is the child process" + Pyroscope.tag_wrapper({"fork": "forked"}) do + slow_function() + end +end + +puts "This is the master process." + +Pyroscope.tag_wrapper({"fork": "master"}) do + fast_function() +end + +puts "The PID of the child process is #{child_pid}" + +Pyroscope.shutdown() diff --git a/src/backend/types.rs b/src/backend/types.rs index 1b0657f1..984ae666 100644 --- a/src/backend/types.rs +++ b/src/backend/types.rs @@ -147,6 +147,11 @@ impl Report { } } + /// Return an iterator over the StackTraces of the Report. + pub fn iter(&self) -> impl Iterator { + self.data.iter() + } + /// Set the metadata of the report. pub fn metadata(self, metadata: Metadata) -> Self { Self { @@ -254,6 +259,11 @@ impl StackTrace { metadata, } } + + /// Return an iterator over the frames of the stacktrace. + pub fn iter(&self) -> impl Iterator { + self.frames.iter() + } } /// StackFrame diff --git a/src/pyroscope.rs b/src/pyroscope.rs index 239fe0d6..32edae81 100644 --- a/src/pyroscope.rs +++ b/src/pyroscope.rs @@ -9,7 +9,7 @@ use std::{ }; use crate::{ - backend::{void_backend, BackendReady, BackendUninitialized, Rule, Tag, VoidConfig}, + backend::{void_backend, BackendReady, BackendUninitialized, Report, Rule, Tag, VoidConfig}, error::Result, session::{Session, SessionManager, SessionSignal}, timer::{Timer, TimerSignal}, @@ -42,6 +42,8 @@ pub struct PyroscopeConfig { pub spy_name: String, /// Authentication Token pub auth_token: Option, + /// Function to apply + pub func: Option Report>, } impl Default for PyroscopeConfig { @@ -56,6 +58,7 @@ impl Default for PyroscopeConfig { sample_rate: 100u32, spy_name: "undefined".to_string(), auth_token: None, + func: None, } } } @@ -76,6 +79,7 @@ impl PyroscopeConfig { sample_rate: 100u32, // Default sample rate spy_name: String::from("undefined"), // Spy Name should be set by the backend auth_token: None, // No authentication token + func: None, // No function } } @@ -116,6 +120,14 @@ impl PyroscopeConfig { } } + /// Set the Function. + pub fn func(self, func: fn(Report) -> Report) -> Self { + Self { + func: Some(func), + ..self + } + } + /// Set the tags. /// /// # Example @@ -243,6 +255,24 @@ impl PyroscopeAgentBuilder { } } + /// Set the Function. + /// This is optional. If not set, the agent will not apply any function. + /// #Example + /// ```ignore + /// let builder = PyroscopeAgentBuilder::new("http://localhost:8080", "my-app") + /// .func(|report| { + /// report + /// }) + /// .build() + /// ?; + /// ``` + pub fn func(self, func: fn(Report) -> Report) -> Self { + Self { + config: self.config.func(func), + ..self + } + } + /// Set tags. Default is empty. /// /// # Example @@ -424,7 +454,7 @@ impl PyroscopeAgent { } impl PyroscopeAgent { - /// Short-hand for PyroscopeAgentBuilder::build(). This is a convenience method. + /// Short-hand for PyroscopeAgentBuilder::new(url, application_name). This is a convenience method. /// /// # Example /// ```ignore @@ -434,6 +464,18 @@ impl PyroscopeAgent { // Build PyroscopeAgent PyroscopeAgentBuilder::new(url, application_name) } + + /// Short-hand for PyroscopeAgentBuilder::default(). This is a convenience method. + /// Default URL is "http://localhost:4040". Default application name is randomly generated. + /// + /// # Example + /// ```ignore + /// let agent = PyroscopeAgent::default_builder().build()?; + /// ``` + pub fn default_builder() -> PyroscopeAgentBuilder { + // Build PyroscopeAgent + PyroscopeAgentBuilder::default() + } } impl PyroscopeAgent { diff --git a/src/session.rs b/src/session.rs index f1537418..15e79e1d 100644 --- a/src/session.rs +++ b/src/session.rs @@ -86,7 +86,9 @@ impl SessionManager { /// Used to contain the session data, and send it to the server. #[derive(Clone, Debug)] pub struct Session { + // Pyroscope instance configuration pub config: PyroscopeConfig, + // Session data pub reports: Vec, // unix time pub from: u64, @@ -150,8 +152,16 @@ impl Session { self.until ); + // own the report + let mut report_owned = report.to_owned(); + + // Apply function to the report + if let Some(func) = self.config.func.clone() { + report_owned = func(report_owned); + } + // Convert a report to a byte array - let report_u8 = report.to_string().into_bytes(); + let report_u8 = report_owned.to_string().into_bytes(); // Check if the report is empty if report_u8.is_empty() { @@ -171,8 +181,7 @@ impl Session { )?; // Parse URL - let parsed_url = Url::parse(&url)?; - let joined = parsed_url.join("ingest")?; + let joined = Url::parse(&url)?.join("ingest")?; // Create Reqwest builder let mut req_builder = client @@ -180,10 +189,6 @@ impl Session { .header("Content-Type", "binary/octet-stream"); // Set authentication token - //if self.config.auth_token.is_some() { - //req_builder = req_builder.bearer_auth(self.config.auth_token.clone().unwrap()); - //} - // rewrite with let some if let Some(auth_token) = self.config.auth_token.clone() { req_builder = req_builder.bearer_auth(auth_token); }