Repository: yabeda-rb/yabeda-rails Branch: master Commit: 9fbdca63efe2 Files: 22 Total size: 30.7 KB Directory structure: gitextract__sq7l337/ ├── .github/ │ └── workflows/ │ ├── lint.yml │ ├── release.yml │ └── test.yml ├── .gitignore ├── .rspec ├── .rubocop.yml ├── CHANGELOG.md ├── Gemfile ├── LICENSE.txt ├── README.md ├── Rakefile ├── bin/ │ ├── console │ └── setup ├── lib/ │ └── yabeda/ │ ├── rails/ │ │ ├── config.rb │ │ ├── event.rb │ │ ├── railtie.rb │ │ └── version.rb │ └── rails.rb ├── spec/ │ ├── spec_helper.rb │ ├── support/ │ │ └── rails_app.rb │ └── yabeda/ │ └── rails_spec.rb └── yabeda-rails.gemspec ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/workflows/lint.yml ================================================ name: Lint on: pull_request: push: branches: - '**' tags-ignore: - 'v*' jobs: rubocop: # Skip running tests for local pull requests (use push event instead), run only for foreign ones if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.owner.login != github.event.pull_request.base.repo.owner.login name: RuboCop runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: ruby-version: "3.4" bundler-cache: true - name: Lint Ruby code with RuboCop run: | bundle exec rubocop ================================================ FILE: .github/workflows/release.yml ================================================ name: Build and release gem on: push: tags: - v* jobs: release: runs-on: ubuntu-latest permissions: contents: write id-token: write packages: write steps: - uses: actions/checkout@v4 with: fetch-depth: 0 # Fetch current tag as annotated. See https://github.com/actions/checkout/issues/290 - uses: ruby/setup-ruby@v1 with: ruby-version: "3.4" - name: "Extract data from tag: version, message, body" id: tag run: | git fetch --tags --force # Really fetch annotated tag. See https://github.com/actions/checkout/issues/290#issuecomment-680260080 echo ::set-output name=version::${GITHUB_REF#refs/tags/v} echo ::set-output name=subject::$(git for-each-ref $GITHUB_REF --format='%(contents:subject)') BODY="$(git for-each-ref $GITHUB_REF --format='%(contents:body)')" # Extract changelog entries between this and previous version headers escaped_version=$(echo ${GITHUB_REF#refs/tags/v} | sed -e 's/[]\/$*.^[]/\\&/g') changelog=$(awk "BEGIN{inrelease=0} /## ${escaped_version}/{inrelease=1;next} /## [0-9]+\.[0-9]+\.[0-9]+/{inrelease=0;exit} {if (inrelease) print}" CHANGELOG.md) # Multiline body for release. See https://github.community/t/set-output-truncates-multiline-strings/16852/5 BODY="${BODY}"$'\n'"${changelog}" BODY="${BODY//'%'/'%25'}" BODY="${BODY//$'\n'/'%0A'}" BODY="${BODY//$'\r'/'%0D'}" echo "::set-output name=body::$BODY" # Add pre-release option if tag name has any suffix after vMAJOR.MINOR.PATCH if [[ ${GITHUB_REF#refs/tags/} =~ ^v[0-9]+\.[0-9]+\.[0-9]+.+ ]]; then echo ::set-output name=prerelease::true fi - name: Build gem run: gem build - name: Calculate checksums run: sha256sum yabeda-rails-${{ steps.tag.outputs.version }}.gem > SHA256SUM - name: Check version run: ls -l yabeda-rails-${{ steps.tag.outputs.version }}.gem - name: Create Release id: create_release uses: actions/create-release@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: ${{ github.ref }} release_name: ${{ steps.tag.outputs.subject }} body: ${{ steps.tag.outputs.body }} draft: false prerelease: ${{ steps.tag.outputs.prerelease }} - name: Upload built gem as release asset uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} asset_path: yabeda-rails-${{ steps.tag.outputs.version }}.gem asset_name: yabeda-rails-${{ steps.tag.outputs.version }}.gem asset_content_type: application/x-tar - name: Upload checksums as release asset uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} asset_path: SHA256SUM asset_name: SHA256SUM asset_content_type: text/plain - name: Publish to GitHub packages env: GEM_HOST_API_KEY: Bearer ${{ secrets.GITHUB_TOKEN }} run: | gem push yabeda-rails-${{ steps.tag.outputs.version }}.gem --host https://rubygems.pkg.github.com/${{ github.repository_owner }} - name: Configure RubyGems Credentials uses: rubygems/configure-rubygems-credentials@main - name: Publish to RubyGems run: | gem push yabeda-rails-${{ steps.tag.outputs.version }}.gem ================================================ FILE: .github/workflows/test.yml ================================================ name: Tests on: pull_request: push: branches: - '**' tags-ignore: - 'v*' jobs: test: name: 'Rails ${{ matrix.rails }} × Ruby ${{ matrix.ruby }}' # Skip running tests for local pull requests (use push event instead), run only for foreign ones if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.owner.login != github.event.pull_request.base.repo.owner.login runs-on: ubuntu-latest continue-on-error: ${{ matrix.optional || false }} strategy: fail-fast: false matrix: include: - ruby: "head" rails: "HEAD" optional: true - ruby: "4.0" rails: "8.1" - ruby: "3.4" rails: "8.1" - ruby: "3.4" rails: "8.0" - ruby: "3.3" rails: "7.2" - ruby: "3.2" rails: "7.1" - ruby: "3.1" rails: "7.0" - ruby: "3.0" rails: "6.1" - ruby: "2.7" rails: "6.0" env: CI: true RAILS_VERSION: ${{ matrix.rails }} steps: - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} bundler-cache: true - name: Run RSpec run: bundle exec rspec ================================================ FILE: .gitignore ================================================ /.bundle/ /.yardoc /_yardoc/ /coverage/ /doc/ /pkg/ /spec/reports/ /tmp/ Gemfile.lock # rspec failure tracking .rspec_status ================================================ FILE: .rspec ================================================ --format documentation --color --require spec_helper ================================================ FILE: .rubocop.yml ================================================ --- require: - rubocop-rspec AllCops: TargetRubyVersion: 2.5 Metrics/BlockLength: Exclude: - "Gemfile" - "spec/**/*" Style/StringLiterals: EnforcedStyle: double_quotes # Allow to use let! RSpec/LetSetup: Enabled: false RSpec/MultipleExpectations: Enabled: false Bundler/OrderedGems: Enabled: false Style/TrailingCommaInArguments: Description: 'Checks for trailing comma in argument lists.' StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-trailing-params-comma' Enabled: true EnforcedStyleForMultiline: consistent_comma Style/TrailingCommaInArrayLiteral: Description: 'Checks for trailing comma in array literals.' StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-trailing-array-commas' Enabled: true EnforcedStyleForMultiline: consistent_comma Style/TrailingCommaInHashLiteral: Description: 'Checks for trailing comma in hash literals.' StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-trailing-array-commas' Enabled: true EnforcedStyleForMultiline: consistent_comma Bundler/DuplicatedGem: Enabled: false ================================================ FILE: CHANGELOG.md ================================================ # Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## 0.11.0 - 2025-12-03 ### Added - Ability to use procs and regexps in `ignore_actions` configuration. [@lewispb][] in [#34](https://github.com/yabeda-rb/yabeda-rails/pull/34), [@Envek][] ## 0.10.0 - 2025-09-09 ### Added - Add Passenger server to auto register list [@mabrikan][] in [#28](https://github.com/yabeda-rb/yabeda-rails/pull/28) - Allow defining default_tags only for rails group [@magec][] in [#30](https://github.com/yabeda-rb/yabeda-rails/pull/30) - Ability to customize the bucket sizing for histograms [@skateman][] in [#32](https://github.com/yabeda-rb/yabeda-rails/pull/32) - Ability to ignore certain controller#actions [@zzip][] in [#33](https://github.com/yabeda-rb/yabeda-rails/pull/33) ## 0.9.0 - 2023-08-03 ### Added - Ability to switch controller name case in `controller` tag between `:snake` and `:camel` case. [@lewispb][] in [#26](https://github.com/yabeda-rb/yabeda-rails/pull/26) ## Changed - Minimal Ruby version increased to 2.5. [@Envek][] ## 0.8.1 - 2022-06-06 ### Fixed - Fill status codes for responses with unhandled exceptions. [@dks17][] in [#24](https://github.com/yabeda-rb/yabeda-rails/pull/24) ## 0.8.0 - 2022-05-30 ### Added - Add ability to expose custom Apdex target value for later use in graphs/alerts. [@Envek][] in [#18](https://github.com/yabeda-rb/yabeda-rails/pull/18) ### Changed - Reduce number of dependencies by depending only on railties instead of the whole Ruby on Rails. [@lautis][] in [#23](https://github.com/yabeda-rb/yabeda-rails/pull/23). ## 0.7.2 - 2021-03-15 ### Fixed - Fix undesirable overwrite of metric tags when global `default_tag` is declared with one of tag names that are being used by yabeda-rails, like `controller`. [@liaden] in [#19](https://github.com/yabeda-rb/yabeda-rails/pull/19) ## 0.7.1 - 2020-10-02 ### Changed - Explicitly require previously removed railtie to fix case when it doesn't get required in `yabeda` gem (if `yabeda` is required before `rails`). See [yabeda-rb/yabeda#15](https://github.com/yabeda-rb/yabeda/issues/15). @Envek ## 0.7.0 - 2020-08-21 ### Removed - Railtie to configure Yabeda – it is moved into Yabeda itself. Increase required Yabeda version to keep behavior for users who require only `yabeda-rails` in their Gemfiles. @Envek ## 0.6.0 - 2020-08-06 ### Added - Ability to add default/custom tags to metrics from controllers. @raivil in [#13](https://github.com/yabeda-rb/yabeda-rails/pull/13) ## 0.5.0 - 2020-03-27 ### Added - Support for Unicorn application server. @vast in [#9](https://github.com/yabeda-rb/yabeda-rails/pull/9) ## 0.4.0 - 2020-01-28 ### Changed - Configure Yabeda after application initialization as since 0.4.0 Yabeda requires to call configuration logic explicitly. @Envek ## 0.2.0 - 2020-01-14 ### Changed - Added `tags` option to metric declarations for compatibility with yabeda and yabeda-prometheus 0.2. @Envek ## 0.1.2 - 2019-01-19 ### Added - Support for Puma application server. @daffydowden ## 0.1.1 - 2018-10-17 ### Changed - Renamed evil-metrics-rails gem to yabeda-rails. @Envek ## 0.1.0 - 2018-10-03 - Initial release of evil-metrics-rails gem. @Envek Basic metrics for request durations by controller, action, status, format, and method. ActiveRecord and ActionView timings. [@Envek]: https://github.com/Envek "Andrey Novikov" [@liaden]: https://github.com/liaden "Joel Johnson" [@lautis]: https://github.com/lautis "Ville Lautanala" [@dks17]: https://github.com/dks17 "Konstantin" [@lewispb]: https://github.com/lewispb "Lewis Buckley" [@mabrikan]: https://github.com/mabrikan "Musaed Albrikan" [@magec]: https://github.com/magec "Jose Fernández" [@skateman]: https://github.com/skateman "Halász Dávid" [@zzip]: https://github.com/zzip "Dale Hofkens" ================================================ FILE: Gemfile ================================================ # frozen_string_literal: true source "https://rubygems.org" git_source(:github) { |repo_name| "https://github.com/#{repo_name}" } # Specify your gem's dependencies in yabeda-rails.gemspec gemspec rails_version = ENV.fetch("RAILS_VERSION", "~> 8.0") case rails_version when "HEAD" git "https://github.com/rails/rails.git" do gem "rails" gem "activesupport" gem "railties" end else rails_version = "~> #{rails_version}.0" if rails_version.match?(/^\d+\.\d+$/) gem "rails", rails_version gem "activesupport", rails_version gem "railties", rails_version end group :development, :test do gem "yabeda", "~> 0.11" # Test helpers gem "rspec-rails" gem "debug" gem "rubocop", "~> 1.8" gem "rubocop-rspec" end ================================================ FILE: LICENSE.txt ================================================ The MIT License (MIT) Copyright (c) 2018 Andrey Novikov Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # ![Yabeda::Rails](./yabeda-rails-logo.png) Built-in metrics for out-of-the box [Rails] applications monitoring. If your monitoring system already collects Rails metrics (e.g. NewRelic) then most probably you don't need this gem. Sample Grafana dashboard ID: [11668](https://grafana.com/grafana/dashboards/11668) ## Installation Add this line to your application's Gemfile: ```ruby gem 'yabeda-rails' # Then add monitoring system adapter, e.g.: # gem 'yabeda-prometheus' ``` And then execute: $ bundle ### Registering metrics on server process start Currently, yabeda-rails automatically registers rails metrics when a server is started via `rails server`, `puma -C config/puma.rb` or `unicorn -c`. However, other application servers or launching via `rackup` aren't supported at the moment. A possible workaround is to detect server process and manually activate yabeda-rails in an initializer: ```ruby # config/initializers/yabeda.rb if your_app_server_process? # Your logic here Yabeda::Rails.install! end ``` You always can add support for your app server to [lib/yabeda/rails/railtie.rb](lib/yabeda/rails/railtie.rb). Pull Requests are always welcome! ## Metrics - Total web requests received: `rails_requests_total` - Web request duration: `rails_request_duration` (in seconds) - Views rendering duration: `rails_view_runtime` (in seconds) - DB request duration: `rails_db_runtime` (in seconds) ## Hooks - `on_controller_action`: Allows to collect ```ruby Yabeda::Rails.on_controller_action do |event, labels| next unless event.payload[:ext_service_runtime] time_in_seconds = event.payload[:ext_service_runtime] / 1000.0 rails_ext_service_runtime.measure(labels, time_in_seconds) end ``` ## Custom tags You can add additional tags to the existing metrics by adding custom payload to your controller. ```ruby # This block is optional but some adapters (like Prometheus) requires that all tags should be declared in advance Yabeda.configure do default_tag :importance, nil end class ApplicationController < ActionController::Base def append_info_to_payload(payload) super payload[:importance] = extract_importance(params) end end ``` `append_info_to_payload` is a method from [ActionController::Instrumentation](https://api.rubyonrails.org/classes/ActionController/Instrumentation.html#method-i-append_info_to_payload) ## Configuration Configuration is handled by [anyway_config] gem. With it you can load settings from environment variables (upcased and prefixed with `YABEDA_RAILS_`), YAML files, and other sources. See [anyway_config] docs for details. | Config key | Type | Default | Description | | ---------------------- | ------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | | `apdex_target` | integer | nil | Tolerable time for Apdex in seconds, exposed as gauge if set. | | `controller_name_case` | symbol | :snake | Defines whether controller name is reported in camel case (:camel) or snake case (:snake). | | `ignore_actions` | array or proc | [] | array of controller#action strings or a proc that receives the controller#action string and returns true if the action should be ignored. Controller should be in camel case, example `['HealthCheck::HealthCheckController#index']` or `->(controller_action) { controller_action.start_with?("HealthCheck") }` | ## Development After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment. To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). ### Releasing 1. Bump version number in `lib/yabeda/rails/version.rb` In case of pre-releases keep in mind [rubygems/rubygems#3086](https://github.com/rubygems/rubygems/issues/3086) and check version with command like `Gem::Version.new(Yabeda::Rails::VERSION).to_s` 2. Fill `CHANGELOG.md` with missing changes, add header with version and date. 3. Make a commit: ```sh git add lib/yabeda/rails/version.rb CHANGELOG.md version=$(ruby -r ./lib/yabeda/rails/version.rb -e "puts Gem::Version.new(Yabeda::Rails::VERSION)") git commit --message="${version}: " --edit ``` 4. Create annotated tag: ```sh git tag v${version} --annotate --message="${version}: " --edit --sign ``` 5. Fill version name into subject line and (optionally) some description (list of changes will be taken from changelog and appended automatically) 6. Push it: ```sh git push --follow-tags ``` 7. You're done! ## Contributing Bug reports and pull requests are welcome on GitHub at https://github.com/yabeda-rb/yabeda-rails. ## License The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT). [Rails]: https://rubyonrails.org "Ruby on Rails MVC web-application framework optimized for programmer happiness" ================================================ FILE: Rakefile ================================================ # frozen_string_literal: true require "bundler/gem_tasks" require "rspec/core/rake_task" RSpec::Core::RakeTask.new(:spec) task default: :spec ================================================ FILE: bin/console ================================================ #!/usr/bin/env ruby # frozen_string_literal: true require "bundler/setup" require "yabeda/rails" # You can add fixtures and/or initialization code here to make experimenting # with your gem easier. You can also use a different console, if you like. require "pry" Pry.start ================================================ FILE: bin/setup ================================================ #!/usr/bin/env bash set -euo pipefail IFS=$'\n\t' set -vx bundle install # Do any other automated setup that you need to do here ================================================ FILE: lib/yabeda/rails/config.rb ================================================ # frozen_string_literal: true require "anyway" module Yabeda module Rails # yabeda-rails configuration class Config < ::Anyway::Config config_name :yabeda_rails attr_config :apdex_target attr_config :buckets attr_config controller_name_case: :snake attr_config ignore_actions: [] end end end ================================================ FILE: lib/yabeda/rails/event.rb ================================================ # frozen_string_literal: true module Yabeda module Rails # ActiveSupport Event with added logic for Yabeda tags formatting class Event < ActiveSupport::Notifications::Event def labels @labels ||= begin labels = { controller: controller, action: action, status: status, format: format, method: method, } labels.merge(payload.slice(*(Yabeda.default_tags.keys + Yabeda.rails.default_tags.keys) - labels.keys)) end end def duration ms2s super end def view_runtime ms2s payload[:view_runtime] end def db_runtime ms2s payload[:db_runtime] end def controller_action "#{payload[:controller]}##{payload[:action]}" end private def controller case Yabeda::Rails.config.controller_name_case when :camel payload[:controller] else payload[:params]["controller"] end end def action payload[:action] end def status if payload[:status].nil? && payload[:exception].present? ActionDispatch::ExceptionWrapper.status_code_for_exception(payload[:exception].first) else payload[:status] end end def format payload[:format] end def method payload[:method].downcase end def ms2s(milliseconds) (milliseconds.to_f / 1000).round(3) end end end end ================================================ FILE: lib/yabeda/rails/railtie.rb ================================================ # frozen_string_literal: true # Explicitly require yabeda's railtie in case if its require was skipped there. # See https://github.com/yabeda-rb/yabeda/issues/15 require "yabeda/railtie" module Yabeda module Rails class Railtie < ::Rails::Railtie # :nodoc: def rails_server? ::Rails.const_defined?(:Server) end def puma_server? ::Rails.const_defined?("Puma::CLI") end def unicorn_server? ::Rails.const_defined?("Unicorn::Launcher") end def passenger_server? ::Rails.const_defined?("PhusionPassenger") end initializer "yabeda-rails.metrics" do ::Yabeda::Rails.install! if rails_server? || puma_server? || unicorn_server? || passenger_server? end end end end ================================================ FILE: lib/yabeda/rails/version.rb ================================================ # frozen_string_literal: true module Yabeda module Rails VERSION = "0.11.0" end end ================================================ FILE: lib/yabeda/rails.rb ================================================ # frozen_string_literal: true require "yabeda" require "active_support" require "rails/railtie" require "yabeda/rails/railtie" require "yabeda/rails/config" require "yabeda/rails/event" module Yabeda # Minimal set of Rails-specific metrics for using with Yabeda module Rails LONG_RUNNING_REQUEST_BUCKETS = [ 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, # standard 30, 60, 120, 300, 600, # Sometimes requests may be really long-running ].freeze class << self def controller_handlers @controller_handlers ||= [] end def on_controller_action(&block) controller_handlers << block end # Declare metrics and install event handlers for collecting themya # rubocop: disable Metrics/MethodLength, Metrics/BlockLength, Metrics/AbcSize def install! Yabeda.configure do config = ::Yabeda::Rails.config buckets = config.buckets || LONG_RUNNING_REQUEST_BUCKETS group :rails counter :requests_total, comment: "A counter of the total number of HTTP requests rails processed.", tags: %i[controller action status format method] histogram :request_duration, tags: %i[controller action status format method], unit: :seconds, buckets: buckets, comment: "A histogram of the response latency." histogram :view_runtime, unit: :seconds, buckets: buckets, comment: "A histogram of the view rendering time.", tags: %i[controller action status format method] histogram :db_runtime, unit: :seconds, buckets: buckets, comment: "A histogram of the activerecord execution time.", tags: %i[controller action status format method] if config.apdex_target gauge :apdex_target, unit: :seconds, comment: "Tolerable time for Apdex (T value: maximum duration of satisfactory request)" collect { rails_apdex_target.set({}, config.apdex_target) } end ActiveSupport::Notifications.subscribe "process_action.action_controller" do |*args| event = Yabeda::Rails::Event.new(*args) # rubocop: disable Style/CaseEquality next if Array(config.ignore_actions).any? { |action| action === event.controller_action } # rubocop: enable Style/CaseEquality rails_requests_total.increment(event.labels) rails_request_duration.measure(event.labels, event.duration) rails_view_runtime.measure(event.labels, event.view_runtime) rails_db_runtime.measure(event.labels, event.db_runtime) Yabeda::Rails.controller_handlers.each do |handler| handler.call(event, event.labels) end end end end # rubocop: enable Metrics/MethodLength, Metrics/BlockLength, Metrics/AbcSize def config @config ||= Config.new end end end end ================================================ FILE: spec/spec_helper.rb ================================================ # frozen_string_literal: true ENV["RAILS_ENV"] = "test" require "bundler/setup" require "logger" require "debug" require "yabeda/rails" require "yabeda/rspec" require_relative "support/rails_app" require "rspec/rails" RSpec.configure do |config| # Enable flags like --only-failures and --next-failure config.example_status_persistence_file_path = ".rspec_status" # Disable RSpec exposing methods globally on `Module` and `main` config.disable_monkey_patching! config.expect_with :rspec do |c| c.syntax = :expect end Kernel.srand config.seed config.order = :random config.before(:suite) do Yabeda::Rails.install! end end ================================================ FILE: spec/support/rails_app.rb ================================================ # frozen_string_literal: true require "rails" require "action_controller/railtie" require "active_support/railtie" class TestApplication < Rails::Application config.logger = Logger.new($stdout) config.log_level = :fatal config.consider_all_requests_local = true config.eager_load = true routes.append do get "/hello/world" => "hello#world" get "/hello/long" => "hello#long" get "/hello/internal_server_error" => "hello#internal_server_error" end end class HelloController < ActionController::API def append_info_to_payload(payload) super payload[:custom_tag_from_rails] = "hello-world-from-rails" payload[:custom_tag] = "hello-world" end def world render json: { hello: :world } end def long sleep(0.01) render json: { good: :morning } end def internal_server_error raise StandardError end end TestApplication.initialize! ================================================ FILE: spec/yabeda/rails_spec.rb ================================================ # frozen_string_literal: true require "action_controller/test_case" RSpec.describe Yabeda::Rails, type: :integration do include ActionDispatch::Integration::Runner include ActionDispatch::IntegrationTest::Behavior def app TestApplication end it "increments counters for every request" do expect { get "/hello/world" }.to \ increment_yabeda_counter(Yabeda.rails.requests_total) .with_tags(controller: "hello", action: "world", status: 200, method: "get", format: :html) .by(1) end it "measure action runtime for every request" do expect { get "/hello/long" }.to \ measure_yabeda_histogram(Yabeda.rails.request_duration) .with_tags(controller: "hello", action: "long", status: 200, method: "get", format: :html) .with(be_between(0.005, 0.05)) end it "returns internal_server_error status code" do expect { get "/hello/internal_server_error" }.to \ increment_yabeda_counter(Yabeda.rails.requests_total) .with_tags(controller: "hello", action: "internal_server_error", status: 500, method: "get", format: :html) end context "with changed controller name case config tp camel case" do around do |example| original_case = described_class.config.controller_name_case described_class.config.controller_name_case = :camel example.call ensure described_class.config.controller_name_case = original_case end it "reports controller tag in camel case" do expect { get "/hello/world" }.to \ increment_yabeda_counter(Yabeda.rails.requests_total) .with_tags(controller: "HelloController", action: "world", status: 200, method: "get", format: :html) .by(1) end end context "with default_tags set" do before do Yabeda.default_tag :custom_tag, nil end it "increments counters for every request" do expect { get "/hello/world" }.to \ increment_yabeda_counter(Yabeda.rails.requests_total) .with_tags(custom_tag: "hello-world") .by(1) end end context "with ':rails' default_tags set" do before do Yabeda.default_tag :custom_tag_from_rails, nil, group: :rails end it "increments counters for every request" do expect { get "/hello/world" }.to \ increment_yabeda_counter(Yabeda.rails.requests_total) .with_tags(custom_tag_from_rails: "hello-world-from-rails") .by(1) end end context "with ignore_actions" do around do |example| original_ignore_actions = described_class.config.ignore_actions described_class.config.ignore_actions = ["HelloController#world", "HelloController#long"] example.call ensure described_class.config.ignore_actions = original_ignore_actions end it "ignores actions matching the proc" do expect { get "/hello/world" }.not_to \ increment_yabeda_counter(Yabeda.rails.requests_total) end end context "with ignore_actions as a proc" do around do |example| original_ignore_actions = described_class.config.ignore_actions described_class.config.ignore_actions = lambda { |controller_action| controller_action.start_with?("HelloController#") } example.call ensure described_class.config.ignore_actions = original_ignore_actions end it "ignores actions matching the proc" do expect { get "/hello/world" }.not_to \ increment_yabeda_counter(Yabeda.rails.requests_total) end end end ================================================ FILE: yabeda-rails.gemspec ================================================ # frozen_string_literal: true lib = File.expand_path("lib", __dir__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require "yabeda/rails/version" Gem::Specification.new do |spec| spec.name = "yabeda-rails" spec.version = Yabeda::Rails::VERSION spec.authors = ["Andrey Novikov"] spec.email = ["envek@envek.name"] spec.summary = "Extensible metrics for monitoring Ruby on Rails application" spec.description = "Easy collecting your Rails apps metrics" spec.homepage = "https://github.com/yabeda-rb/yabeda-rails" spec.license = "MIT" spec.metadata = { "changelog_uri" => "https://github.com/yabeda-rb/yabeda-rails/blob/master/CHANGELOG.md", "rubygems_mfa_required" => "true", } spec.files = `git ls-files -z`.split("\x0").reject do |f| f.match(%r{^(test|spec|features)/}) end spec.bindir = "exe" spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] spec.required_ruby_version = ">= 2.5" spec.add_dependency "activesupport" spec.add_dependency "anyway_config", ">= 1.3", "< 3" spec.add_dependency "railties" spec.add_dependency "yabeda", "~> 0.8" spec.add_development_dependency "bundler", ">= 2.0" spec.add_development_dependency "rake", "~> 13.0" spec.add_development_dependency "rspec", "~> 3.0" end