[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-7934":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":16,"stars30d":17,"stars90d":16,"forks30d":16,"starsTrendScore":16,"compositeScore":18,"rankGlobal":10,"rankLanguage":10,"license":19,"archived":20,"fork":20,"defaultBranch":21,"hasWiki":22,"hasPages":20,"topics":23,"createdAt":10,"pushedAt":10,"updatedAt":29,"readmeContent":30,"aiSummary":31,"trendingCount":16,"starSnapshotCount":16,"syncStatus":32,"lastSyncTime":33,"discoverSource":34},7934,"coverband","danmayer\u002Fcoverband","danmayer","Ruby production code coverage collection and reporting (line of code usage)","https:\u002F\u002Fgithub.com\u002Fdanmayer\u002Fcoverband",null,"Ruby",2680,171,14,1,0,8,28.71,"MIT License",false,"main",true,[24,25,5,26,27,28],"coverage-data","coverage-report","rack-middleware","rails","ruby","2026-06-12 02:01:46","\u003Cimg src=\"https:\u002F\u002Fraw.github.com\u002Fdanmayer\u002Fcoverband\u002Fmain\u002Fdocs\u002Fassets\u002Flogo\u002Fheads.svg?sanitize=true\" width='300'>\n\n# Coverband\n\n[![GithubCI](https:\u002F\u002Fgithub.com\u002Fdanmayer\u002Fcoverband\u002Fworkflows\u002FCI\u002Fbadge.svg)](https:\u002F\u002Fgithub.com\u002Fdanmayer\u002Fcoverband\u002Factions)\n[![Coverage Status](https:\u002F\u002Fcoveralls.io\u002Frepos\u002Fgithub\u002Fdanmayer\u002Fcoverband\u002Fbadge.svg?branch=main)](https:\u002F\u002Fcoveralls.io\u002Fgithub\u002Fdanmayer\u002Fcoverband?branch=main)\n[![Maintainability](https:\u002F\u002Fapi.codeclimate.com\u002Fv1\u002Fbadges\u002F1e6682f9540d75f26da7\u002Fmaintainability)](https:\u002F\u002Fcodeclimate.com\u002Fgithub\u002Fdanmayer\u002Fcoverband\u002Fmaintainability)\n[![Discord Shield](https:\u002F\u002Fimg.shields.io\u002Fdiscord\u002F609509533999562753)](https:\u002F\u002Fdiscord.gg\u002FKAH38EV)\n\n\u003Cp align=\"center\">\n  \u003Ca href=\"#key-features\">Key Features\u003C\u002Fa> •\n  \u003Ca href=\"#installation\">Installation\u003C\u002Fa> •\n  \u003Ca href=\"#coverband-web-ui\">Coverband Web UI\u003C\u002Fa> •\n  \u003Ca href=\"#advanced-config\">Advanced Config\u003C\u002Fa> •\n  \u003Ca href=\"#newer-features\">Newer Features\u003C\u002Fa> •\n  \u003Ca href=\"#license\">License\u003C\u002Fa> •\n  \u003Ca href=\"\u002Fchanges.md\">Change Log \u002F Roadmap\u003C\u002Fa> •\n  \u003Ca href=\"\u002FCODE_OF_CONDUCT.md\">Code of Conduct\u003C\u002Fa>\n\u003C\u002Fp>\n\nA gem to measure production code usage, showing a counter for the number of times each line of code is executed. Coverband allows easy configuration to collect and report on production code usage. It reports in the background via a thread, can be used as Rack middleware, or can be manually configured to meet any need.\n\n**Note:** Coverband is not intended for test code coverage; for that we recommend using [SimpleCov](https:\u002F\u002Fgithub.com\u002Fcolszowka\u002Fsimplecov).\n\n## Key Features\n\nThe primary goal of Coverband is to give you deep insight into the production runtime usage of your application code, while having the least impact on performance possible.\n\n- Low performance overhead\n- Simple setup and configuration\n- Out of the box support for all standard code execution paths (web, cron, background jobs, rake tasks, etc)\n- Splits code loading usage (Rails eager load) and runtime usage metrics\n- Easy to understand actionable insights from the report\n- Mountable web interface to easily share reports\n\n# Installation\n\n## Redis\n\nCoverband stores coverage data in Redis. The Redis endpoint is looked for in this order:\n\n1. `ENV['COVERBAND_REDIS_URL']`\n2. `ENV['REDIS_URL']`\n3. `localhost:6379`\n\nThe redis store can also be explicitly defined within the `config\u002Fcoverband.rb`. See [advanced config](#advanced-config).\n\n### Redis with TLS\n\nFor Redis servers that require TLS (such as AWS serverless ElastiCache), use the `rediss:\u002F\u002F` URL scheme instead of `redis:\u002F\u002F`. The Redis gem automatically enables TLS when it detects this scheme:\n\n```bash\n# Example with AWS serverless ElastiCache\nREDIS_URL=rediss:\u002F\u002Fmy-elasticache.abcdef.cache.amazonaws.com:6379\n```\n\nOr in `config\u002Fcoverband.rb`:\n\n```ruby\nconfig.store = Coverband::Adapters::RedisStore.new(\n  Redis.new(url: \"rediss:\u002F\u002Fmy-elasticache-endpoint:6379\")\n)\n```\n\nThe `rediss:\u002F\u002F` scheme works with:\n- AWS ElastiCache (serverless or provisioned with required TLS)\n- Any self-hosted Redis with TLS enabled\n- Other managed Redis services that require TLS\n\n## Gem Installation\n\nAdd this line to your application's `Gemfile`, remember to `bundle install` after updating:\n\n```bash\ngem 'coverband'\n```\n\n### No custom code or middleware required\n\nWith older versions of Coverband, projects would report to redis using rack or sidekiq middleware. After Coverband 4.0, this should no longer be required and could cause performance issues. Reporting to redis is now automatically done within a background thread with no custom code needed.\n\nSee [changelog](https:\u002F\u002Fgithub.com\u002Fdanmayer\u002Fcoverband\u002Fblob\u002Fmain\u002Fchanges.md).\n\n## Rails\n\nThe Railtie integration means you shouldn't need to do anything else other than ensure Coverband is required after Rails within your Gemfile.\n\n## Sinatra\n\nFor the best coverage, you want this loaded as early as possible. We recommend requiring cover band directly in the `config.ru`. Requiring Coverband within an initializer could also work, but you may end up missing some boot up coverage. To start collection require Coverband as early as possible.\n\n```ruby\nrequire 'coverband'\nrequire File.dirname(__FILE__) + '\u002Fconfig\u002Fenvironment'\n\nuse Coverband::BackgroundMiddleware\nrun ActionController::Dispatcher.new\n```\n\n## Coverband Web UI\n\n![image](https:\u002F\u002Fraw.github.com\u002Fdanmayer\u002Fcoverband\u002Fmain\u002Fdocs\u002Fcoverband_web_ui.png)\n\n> You can check it out locally by running the [Coverband Demo App](https:\u002F\u002Fgithub.com\u002Fdanmayer\u002Fcoverband_rails_example).\n\n- View a shared demo at [https:\u002F\u002Fcoverband-rails-example.onrender.com\u002F](https:\u002F\u002Fcoverband-rails-example.onrender.com\u002F)\n\n- View overall coverage information\n\n- Drill into individual file coverage\n\n- View individual file details\n\n- Clear Coverage - disabled by default as it could be considered a dangerous operation in production. Enable with `config.web_enable_clear` or leave off and clear from the [rake task](#clear-coverage).\n\n  - Clear coverage report\n\n    This will clear the coverage data. This wipes out all collected data.\n\n  - Clear individual file coverage\n\n    This will clear the details of the file you are looking at. This is helpful if you don't want to lose all Coverage data but made a change that you expect would impact a particular file.\n\n- Force coverage collection\n\n  This triggers coverage collection on the current webserver process. Useful in development but confusing in production environments where many ruby processes are usually running.\n\n#### Interpreting results\n\nThe columns in the web UI are as follows:\n\n- **% covered** - Percentage of total relevant lines covered\n- **% runtime** - Percentage of the runtime lines covered where runtime lines are lines that are hit after the application has been eagerly loaded\n- **Lines** - Total lines in the file including lines unreachable or uncover-able. An unreachable line would be an empty line with no code, comments, or `end` statements.\n- **Relevant lines** - Lines that are coverable, i.e. not empty\n- **Lines runtime** - Total lines minus uncoverable lines minus the lines that are only hit during eager loading of application\n- **Lines missed** - Relevant lines not covered\n- **Avg hits\u002Fline** - Total of coverage to the file divided by relevant lines.\n\nWhen viewing an individual file, a line of code such as a class or method definition may appear green because it is eager loaded by the application, but still not be hit at all in runtime by actual users.  \n\n![example of a file with lines not hit at runtime](https:\u002F\u002Fuser-images.githubusercontent.com\u002F96786\u002F63541229-aa98a580-c4eb-11e9-8eb8-c004fe1369db.png)\n#### Coverage first seen and Last activity recorded\nIn the context of Coverband, a file is considered relevant for monitoring if it is located within certain specified project paths. Specifically, Coverband monitors all *.rb files located in the following paths:\n\n- app\u002F\n\n- lib\u002F\n\n- config\u002F\n\nThis applies as long as these files are not included in the list of exclusions defined in \"config.ignore\".\n\n#### Coverage first seen\nThis attribute shows the exact date and time when Coverband first detected the file. This detection happens when:\n\n- The file is loaded by Ruby (e.g., during application startup in Rails via autoload or require).\n\n- The file becomes relevant for monitoring, even if no lines within it have been executed yet.\n\n- By default, Coverband resets a file’s coverage data and updates its “Coverage first seen” timestamp whenever the file changes, ensuring the coverage reflects the file’s new state.\n\n#### Last activity recorded\nThis attribute shows the most recent time when any line in the file was executed at runtime. It specifically reflects runtime execution and does not include the file’s load time.\n\n- When any line in the file is executed at runtime (e.g., a method is called, a route is triggered, or a conditional is evaluated), Coverband updates the “Last activity recorded” timestamp.\n\n- This only occurs when the file’s lines are actually executed. If a file is loaded but none of its lines are executed, the “Last activity recorded” timestamp will not be updated.\n\n- It helps determine if a file is actively being used in the application. If a file has no recent activity, it may be a candidate for review or removal.\n\n#### Example\n- If a file has a “Coverage first seen” timestamp but no “Last activity recorded”, this indicates that the file is being loaded but no runtime activity is occurring (e.g., it contains unused methods or classes).\n\n- If both attributes are populated and the “Last activity recorded” timestamp is recent, the file is actively used in the application.\n\n### Mounting as a Rack App\n\nCoverband comes with a mountable rack app for viewing reports. For Rails this can be done in `config\u002Froutes.rb` with:\n\n```ruby\nRails.application.routes.draw do\n  mount Coverband::Reporters::Web.new, at: '\u002Fcoverage'\nend\n```\n\nBut don't forget to _protect your source code with proper authentication_. Something like this when using devise:\n\n```ruby\nRails.application.routes.draw do\n  authenticate :user, lambda { |u| u.admin? } do\n    mount Coverband::Reporters::Web.new, at: '\u002Fcoverage'\n  end\nend\n```\n\nor you can enable basic auth by setting `ENV['COVERBAND_PASSWORD']` or via your configuration `config.password = \u003CYOUR_COMPLEX_UNGUESSABLE_PASSWORD>`\n\n### Standalone\n\nThe coverage server can also be started standalone with a rake task:\n\n```\nbundle exec rake coverband:coverage_server\n```\n\nThe web UI should then be available here: http:\u002F\u002Flocalhost:9022\u002F\n\nIf you want to run on an alternative port:\n\n```\nCOVERBAND_COVERAGE_PORT=8086 bundle exec rake coverband:coverage_server\n```\n\nThis is especially useful for projects that are api only and cannot support the mounted rack app. To get production coverage, point Coverband at your production redis server and ensure to checkout the production version of your project code locally.\n\n```\n COVERBAND_REDIS_URL=redis:\u002F\u002Fusername:password@redis_production_server:2322 bundle exec rake coverband:coverage_server\n```\n\n# Coverband Demo\n\nTake Coverband for a spin on the live Heroku deployed [Coverband Demo](https:\u002F\u002Fcoverband-demo.herokuapp.com\u002F). The [full source code for the demo](https:\u002F\u002Fgithub.com\u002Fdanmayer\u002Fcoverband_demo) is available to help with installation, configuration, and understanding of basic usage.\n\n### Example apps\n\n- [Rails 5.2.x App](https:\u002F\u002Fgithub.com\u002Fdanmayer\u002Fcoverband_demo)\n- [Sinatra app](https:\u002F\u002Fgithub.com\u002Fdanmayer\u002Fchurn-site)\n- [Non Rack Ruby app](https:\u002F\u002Fgithub.com\u002Fdanmayer\u002Fcoverband_examples)\n\n# Advanced Config\n\nIf you need to configure Coverband, this can be done by creating a `config\u002Fcoverband.rb` file relative to your project root.\n\n- See [lib\u002Fcoverband\u002Fconfiguration.rb](https:\u002F\u002Fgithub.com\u002Fdanmayer\u002Fcoverband\u002Fblob\u002Fmain\u002Flib\u002Fcoverband\u002Fconfiguration.rb) for all options\n- By default Coverband will try to store data to Redis \\* Redis endpoint is looked for in this order: `ENV['COVERBAND_REDIS_URL']`, `ENV['REDIS_URL']`, or `localhost`\n\nBelow is an example config file for a Rails 5 app:\n\n```ruby\n# config\u002Fcoverband.rb NOT in the initializers\nCoverband.configure do |config|\n  config.store = Coverband::Adapters::RedisStore.new(Redis.new(url: ENV['MY_REDIS_URL']))\n  config.logger = Rails.logger\n\n  # config options false, true. (defaults to false)\n  # true and debug can give helpful and interesting code usage information\n  # and is safe to use if one is investigating issues in production, but it will slightly\n  # hit perf.\n  config.verbose = false\n\n  # default false. button at the top of the web interface which clears all data\n  config.web_enable_clear = true\n\n  # default false. Experimental support for routes usage tracking.\n  config.track_routes = true\nend\n```\n\n### Working with environment variables\n\nDo you use figaro, mc-settings, dotenv or something else to inject environment variables into your app? If so ensure you have that done BEFORE Coverband is required.\n\nFor example if you use dotenv, you need to do this, see https:\u002F\u002Fgithub.com\u002Fbkeepers\u002Fdotenv#load-order\n\n```\ngem 'dotenv', require: 'dotenv\u002Fload'\ngem 'coverband'\ngem 'other-gem-that-requires-env-variables'\n```\n\n### Ignoring Files\n\nSometimes you have files that are known to be valuable, perhaps in other environments or something that is just run very infrequently. Opposed to having to mentally filter them out of the report, you can just have them ignored in the Coverband reporting by using `config.ignore` as shown below. Ignore takes a string but can also match with regex rules see how below ignores all rake tasks as an example.\n\n```\nconfig.ignore +=  ['config\u002Fapplication.rb',\n                   'config\u002Fboot.rb',\n                   'config\u002Fpuma.rb',\n                   'config\u002Fschedule.rb',\n                   'bin\u002F.*',\n                   'config\u002Fenvironments\u002F.*',\n                   'lib\u002Ftasks\u002F.*']\n```\n\n**Ignoring Custom Gem Locations:** Note, if you have your gems in a custom location under your app folder you likely want to add them to `config.ignore`. For example, if you have your gems not in the default ignored location of `app\u002Fvendor` but in `app\u002Fgems`, you would need to add `gems\u002F*` to your ignore list.\n\n### View Tracking\n\nCoverband allows an optional feature to track all view files that are used by an application.\n\nThis feature is enabled by default. To stop this feature, disable the feature in your Coverband config.\n\n`config.track_views = false`\n\n#### ViewComponent Support\n\nCoverband can also track [ViewComponent](https:\u002F\u002Fviewcomponent.org\u002F) renders. This requires:\n\n- ViewComponent **>= 4.6.0**\n- Instrumentation enabled in your app config:\n\n```ruby\n# config\u002Fapplication.rb (or environment-specific config)\nconfig.view_component.instrumentation_enabled = true\n```\n\nWhen enabled, Coverband subscribes to the `render.view_component` notification and tracks which component templates are rendered, just like standard Rails views.\n\n![image](https:\u002F\u002Fraw.github.com\u002Fdanmayer\u002Fcoverband\u002Fmain\u002Fdocs\u002Fcoverband_view_tracker.png)\n\n### Query Burst Tracking\n\nCoverband includes an optional Query Burst Tracker to monitor SQL activity per request and per background job in production. It helps identify potential N+1 query issues and bursty database behavior.\n\nEnable it in your Coverband configuration:\n\n```ruby\nCoverband.configure do |config|\n  config.track_query_bursts = true\n\n  # Thresholds used to flag heavy requests\u002Fjobs\n  config.query_burst_query_count_threshold = 30\n  config.query_burst_sql_time_threshold_ms = 100.0\nend\n```\n\nWhen enabled, Coverband records stats by execution context (for example controller\u002Faction and ActiveJob class) and exposes them in the Query Burst Tracker tab in the web UI.\n\n#### Threshold Settings\n\n- `query_burst_query_count_threshold`:\n  - Max SQL query count allowed for a single tracked execution (one request or one job run).\n  - If query count is greater than or equal to this value, it is counted as a threshold hit.\n- `query_burst_sql_time_threshold_ms`:\n  - Max total SQL time (in milliseconds) allowed for a single tracked execution.\n  - If SQL time is greater than or equal to this value, it is counted as a threshold hit.\n\nThreshold logic is OR-based: Coverband records a threshold hit if either threshold is exceeded.\n\n#### What You See in the UI\n\nFor each tracked key, the Query Burst Tracker reports:\n\n- Requests: Number of tracked executions\n- Total SQL Calls: Sum of all SQL calls across executions\n- Total SQL ms: Sum of SQL time across executions\n- Max SQL Calls: Highest query count seen in one execution\n- Max SQL ms: Highest SQL time seen in one execution\n- Threshold Hits: Number of executions that exceeded either threshold\n\n#### How To Tune Thresholds\n\n- Start with defaults (`30` queries, `100.0` ms SQL time).\n- Lower thresholds to detect smaller regressions sooner.\n- Raise thresholds if you see too much noise from expected heavy endpoints\u002Fjobs.\n- Tune by endpoint\u002Fjob behavior: latency-sensitive paths often need stricter limits than batch work.\n\nTip: use this tracker in production-like traffic, where query patterns are most realistic.\n\n### Hiding settings\n\nCoverband provides a view of all of its current settings. Sometimes you might want to hide this view,\nsuch as when sharing coverband data with a large number of developers of varying trust levels.\nYou can disable the settings view like so:\n\n`config.hide_settings = true`\n\n### Fixing Coverage Only Shows Loading Hits\n\nIf all your coverage is being counted as loading or eager_loading coverage, and nothing is showing as runtime Coverage the initialization hook failed for some reason. The most likely reason for this issue is manually calling `eager_load!` on some Plugin\u002FGem. If you or a plugin is altering the Rails initialization process, you can manually flip Coverband to runtime coverage by calling these two lines, in an `after_initialize` block, in `application.rb`.\n\n```ruby\nconfig.after_initialize do\n  unless Coverband.tasks_to_ignore?\n    Coverband.report_coverage # record the last of the loading coverage\n    Coverband.runtime_coverage! # set all future coverage to runtime\n  end\nend\n```\n\nor if you know you are manually calling eager load anywhere in your initialization process immediately after call those two lines. A user reported an issue after calling `ResqueWeb::Engine.eager_load!` for example.\n\n```ruby\nRails.application.routes.draw do\n  ResqueWeb::Engine.eager_load!\n  Coverband.report_coverage\n  Coverband.runtime_coverage!\nend\n```\n\n### Avoiding Cache Stampede\n\nIf you have many servers and they all hit Redis at the same time you can see spikes in your Redis CPU, and memory. This is due to a concept called [cache stampede](https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FCache_stampede).\n\nIt is better to spread out the reporting across your servers. A simple way to do this is to add a random wiggle on your background reporting. This configuration option allows a wiggle. The right amount of wiggle depends on the number of servers you have and how willing you are to have delays in your coverage reporting. I would recommend at least 1 second per server. Note, the default wiggle is set to 30 seconds.\n\nAdd a wiggle (in seconds) to the background thread to avoid all your servers reporting at the same time:\n\n`config.reporting_wiggle = 30`\n\nThe default 30-second wiggle is suitable for most deployments. For larger fleets you may want to increase the wiggle proportionally (e.g. 1 second per server). The tradeoff is a small delay in coverage reporting freshness. The `reporting_wiggle` and `background_reporting_sleep_seconds` options work together — consider configuring both when tuning background reporting for your environment.\n\nAnother way to avoid cache stampede is to omit some reporting on starting servers. Coverband stores the results of eager_loading to Redis at server startup. The eager_loading results are the same for all servers, so there is no need to save all results. By configuring the eager_loading results of some servers to be stored in Redis, we can reduce the load on Redis during deployment.\n\n```ruby\n# To omit reporting on starting servers, need to defer saving eager_loading data\nconfig.defer_eager_loading_data = true\n# Store eager_loading data on 5% of servers\nconfig.send_deferred_eager_loading_data = rand(100) \u003C 5\n# Store eager_loading data on servers with the environment variable\nconfig.send_deferred_eager_loading_data = ENV.fetch('ENABLE_EAGER_LOADING_COVERAGE', false)\n```\n\nNote: `defer_eager_loading_data = true` is required in order to use `send_deferred_eager_loading_data`. With both set, eager_loading data is deferred at startup and only sent by the subset of servers where `send_deferred_eager_loading_data` evaluates to `true`.\n\n### Oneshot Mode\n\nEnabling [oneshot mode](https:\u002F\u002Fdocs.ruby-lang.org\u002Fen\u002Fmaster\u002FCoverage.html#module-coverage-oneshot-lines-coverage) reduces the Ruby CPU overhead. The tradeoff is that you no longer get frequency data — you will only know whether a line was executed at least once, not how many times.\n\n```ruby\nconfig.use_oneshot_lines_coverage = true\n```\n\n### Redis Hash Store\n\nCoverband on very high volume sites with many server processes reporting can have a race condition which can cause hit counts to be inaccurate. To resolve the race condition and reduce Ruby memory overhead we have introduced a new Redis storage option. This moves the some of the work from the Ruby processes to Redis. It is worth noting because of this, it has larger demands on the Redis server. So adjust your Redis instance accordingly. To help reduce the extra redis load you can also change the background reporting frequency.\n\n- To use Redis Hash Store: `config.store = Coverband::Adapters::HashRedisStore.new(Redis.new(url: redis_url))`\n- Adjust from default 30s reporting `config.background_reporting_sleep_seconds = 120`\n\nSee more discussion [here](https:\u002F\u002Fgithub.com\u002Fdanmayer\u002Fcoverband\u002Fissues\u002F384).\n\n### Clear Coverage\n\nNow that Coverband uses MD5 hashes there should be no reason to manually clear coverage unless one is testing, changing versions, or possibly debugging Coverband itself.\n\n`rake coverband:clear`\n\nThis will clear both the coverage and trackers data. It can also be done through the web if `config.web_enable_clear` is enabled.\n\nTo clear only coverage data, run `rake coverband:clear_coverage`.\nTo clear only trackers data, run `rake coverband:clear_tracker`.\n\n### Adding Rake Tasks outside of Rails\n\nRails apps should automatically include the tasks via the Railtie.\n\nFor non Rails apps, either add the below to your `Rakefile` or to a file included in your `Rakefile` such as `lib\u002Ftasks\u002Fcoverband.rake` if you want to break it up that way.\n\n```ruby\nrequire 'coverband'\nCoverband.configure\nrequire 'coverband\u002Futils\u002Ftasks'\n```\n\nVerify it works\n\n```bash\nrake -T coverband\nrake coverband:clear         # reset coverband coverage data\nrake coverband:coverage      # report runtime coverband code coverage\n```\n\n### Manually Starting Coverband\n\nCoverband starts on require of the the library which is usually done within the Gemfile. This can be disabled by setting the `COVERBAND_DISABLE_AUTO_START` environment variable. This environment variable can be useful to toggle Coverband on and off in certain environments.\n\n**NOTE:** That any value set for `COVERBAND_DISABLE_AUTO_START` is considered true, it does not match the string content but only checks the presence of the ENV variable.\n\nIn order to start Coverband manually when this flag is enabled, call `Coverband.configure` followed by `Coverband.start`.\n\n```ruby\nCoverband.configure\nCoverband.start\n```\n\n### Verbose Debug \u002F Development Mode\n\nNote: To debug issues getting Coverband working. I recommend running in development mode, by turning verbose logging on `config.verbose = true` and passing in the Rails.logger `config.logger = Rails.logger` to the Coverband config. We respect the log level, and I would recommend log level info generally, but if you are investigating a problem Coverband logs additional data at the `debug` level. This makes it easy to follow in development mode. Be careful not to leave these on in production as they will affect performance.\n\n---\n\nIf you are trying to debug locally wondering what code is being run during a request. The verbose modes `config.verbose = true` && `Rails.logger.level = :debug`. With true set it will output the number of lines executed per file, to the passed in log.\n\n### Solving: stack level too deep errors\n\nIf you start seeing SystemStackError: stack level too deep errors from background jobs after installing Coverband, this means there is another patch for ResqueWorker that conflicts with Coverband's patch in your application. To fix this, change Coverband gem line in your Gemfile to the following:\n\n```\ngem 'coverband', require: ['alternative_coverband_patch', 'coverband']\n```\n\nIf you currently have require: false, remove the 'coverband' string from the require array above so the gem line becomes like this:\n\n```\ngem 'coverband', require: ['alternative_coverband_patch']\n```\n\nThis conflict happens when a ruby method is patched twice, once using module prepend, and once using method aliasing. See this ruby issue for details. The fix is to apply all patches the same way. By default, Coverband will apply its patch using prepend, but you can change that to method aliasing by adding require: ['alternative_coverband_patch'] to the gem line as shown above.\n\n### Redis Sizing & Configuration Info\n\nA few folks have asked about what size of Redis is needed to run Coverband. I have some of our largest services with hundreds of servers on cache.m3.medium with plenty of room to spare. I run most apps on the smallest AWS Redis instances available and bump up only if needed or if I am forced to be on a shared Redis instance, which I try to avoid. On Heroku, I have used it with most of the 3rd party and also been fine on the smallest Redis instances, if you have hundreds of dynos you would likely need to scale up. Also note there is a tradeoff one can make, `Coverband::Adapters::HashRedisStore` will use LUA on Redis and increase the Redis load, while being nicer to your app servers and avoid potential lost data during race conditions. While the `Coverband::Adapters::RedisStore` uses in app memory and merging and has lower load on Redis.\n\nFor a dedicated Coverband Redis instance, `allkeys-lfu` is a good choice for `maxmemory-policy` as it evicts the least-frequently-used keys first, meaning rarely-hit files are evicted before frequently-reported ones. On a shared Redis instance, be cautious with eviction policies that could interfere with other data. See [issue #595](https:\u002F\u002Fgithub.com\u002Fdanmayer\u002Fcoverband\u002Fissues\u002F595) for more discussion.\n\n### Ruby Overhead Reduction Checklist\n\nIf Coverband is adding meaningful latency to your application, work through this checklist:\n\n* Enable oneshot mode (`config.use_oneshot_lines_coverage = true`) — reduces CPU overhead by only tracking whether a line ran, not how many times\n* Enable Redis Hash Store — moves merging work from Ruby processes to Redis, reducing per-process memory overhead\n* Only enable Coverband on a subset of server instances — requests routed to those servers will be slightly slower, but coverage data will still be gathered. This is most effective with a Least Outstanding Requests load balancing algorithm. Avoid enabling on all servers but only reporting on a subset of requests — loading the coverage module itself has a performance impact regardless of reporting.\n\n# Newer Features\n\n### MCP Server for AI Assistants\n\nCoverband includes an optional MCP (Model Context Protocol) server that allows AI assistants like Claude to query your production coverage data directly. This enables AI-powered code analysis, dead code detection, and coverage insights.\n\n#### Installation\n\nAdd the MCP gem to your Gemfile:\n\n```ruby\ngem 'mcp'\n```\n\n#### Available Tools\n\nThe MCP server provides the following tools:\n\n| Tool | Description |\n|------|-------------|\n| `get_coverage_summary` | Get overall coverage statistics |\n| `get_file_coverage` | Get detailed coverage for a specific file |\n| `get_uncovered_files` | List files with no coverage data |\n| `get_dead_methods` | Find methods that are never called |\n| `get_view_tracker_data` | Get view\u002Ftemplate usage data |\n| `get_route_tracker_data` | Get route usage statistics |\n| `get_translation_tracker_data` | Get translation key usage data |\n\n#### Running the MCP Server\n\n**Standalone (stdio transport):**\n\n```bash\nbundle exec coverband-mcp\n```\n\n**With a rake task:**\n\n```bash\nbundle exec rake coverband:mcp\n```\n\n**HTTP mode (for remote access):**\n\n```bash\nCOVERBAND_MCP_HTTP=true COVERBAND_MCP_PORT=9023 bundle exec rake coverband:mcp\n```\n\n#### Configuring Claude Desktop\n\nAdd to your Claude Desktop configuration (`~\u002FLibrary\u002FApplication Support\u002FClaude\u002Fclaude_desktop_config.json` on macOS):\n\n**Option 1: Stdio transport (recommended for local development)**\n\n```json\n{\n  \"mcpServers\": {\n    \"coverband\": {\n      \"command\": \"bundle\",\n      \"args\": [\"exec\", \"coverband-mcp\"],\n      \"cwd\": \"\u002Fpath\u002Fto\u002Fyour\u002Frails\u002Fapp\"\n    }\n  }\n}\n```\n\n**Option 2: HTTP transport (for remote access or shared servers)**\n\nFirst, start the MCP server in HTTP mode:\n\n```bash\nCOVERBAND_MCP_HTTP=true bundle exec rake coverband:mcp\n```\n\nThen configure Claude Desktop to connect via `mcp-remote`:\n\n```json\n{\n  \"mcpServers\": {\n    \"coverband\": {\n      \"command\": \"npx\",\n      \"args\": [\"mcp-remote\", \"http:\u002F\u002Flocalhost:9023\"]\n    }\n  }\n}\n```\n\n#### Configuring Claude Code\n\nAdd a `.mcp.json` file to your project root:\n\n**Option 1: Stdio transport (recommended)**\n\n```json\n{\n  \"mcpServers\": {\n    \"coverband\": {\n      \"command\": \"bundle\",\n      \"args\": [\"exec\", \"coverband-mcp\"]\n    }\n  }\n}\n```\n\n**Option 2: HTTP transport**\n\n```json\n{\n  \"mcpServers\": {\n    \"coverband\": {\n      \"command\": \"npx\",\n      \"args\": [\"mcp-remote\", \"http:\u002F\u002Flocalhost:9023\"]\n    }\n  }\n}\n```\n\n#### Environment Variables\n\n| Variable | Description | Default |\n|----------|-------------|---------|\n| `COVERBAND_MCP_HTTP` | Enable HTTP transport instead of stdio | `false` |\n| `COVERBAND_MCP_PORT` | Port for HTTP server | `9023` |\n| `COVERBAND_REDIS_URL` | Redis URL for coverage data | `localhost:6379` |\n\n### Dead Method Scanning (ruby 2.6+)\n\nRake task that outputs dead methods based on current coverage data:\n\n```\nbundle exec rake coverband:dead_methods\n```\n\nOutputs:\n\n```\n---------------------------------------------------------------------------------------------------\n| file                                  | class           | method                  | line_number |\n| .\u002Fconfig\u002Froutes.rb                    | AdminConstraint | matches?                | 20          |\n| .\u002Fapp\u002Fcontrollers\u002Fhome_controller.rb  | HomeController  | trigger_jobs            | 8           |\n| .\u002Fapp\u002Fcontrollers\u002Fhome_controller.rb  | HomeController  | data_tracer             | 14          |\n| .\u002Fapp\u002Fcontrollers\u002Fposts_controller.rb | PostsController | edit                    | 22          |\n| .\u002Fapp\u002Fcontrollers\u002Fposts_controller.rb | PostsController | destroy_bad_dangerously | 73          |\n---------------------------------------------------------------------------------------------------\n```\n\n\n# Prerequisites\n\n- Ruby 3.1+\n- Coverband currently requires Redis for production usage\n\n### Ruby and Rails Version Support\n\nWe will match Heroku & Ruby's support lifetime, supporting the last 3 major Ruby releases. For details see [supported runtimes](https:\u002F\u002Fdevcenter.heroku.com\u002Farticles\u002Fruby-support#supported-runtimes).\n\nFor Rails, we will follow the policy of the [Rails team maintenance policy](https:\u002F\u002Fguides.rubyonrails.org\u002Fmaintenance_policy.html). We officially support the last two major release versions, while providing minimal support (major bugs \u002F security fixes) for an additional version. At the moment we primarily target Rails 7.0+.\n\n### JRuby Support\n\nCoverband is compatible with JRuby. If you want to run on JRuby note that I haven't benchmarked and I believe the perf impact on older versions of JRuby could be significant. Improved Coverage support is in [JRuby master](https:\u002F\u002Fgithub.com\u002Fjruby\u002Fjruby\u002Fpull\u002F6180), and will be in the next release.\n\n- older versions of JRuby need tracing enabled to work (and this could cause bad performance)\n  - run Jruby with the `--debug` option\n  - add into your `.jrubyrc` the `debug.fullTrace=true` setting\n- For best performance the `oneshot_lines` is recommended, and in the latest releases should have very low overhead\n- See JRuby support in a Rails app configured to run via JRuby, in [Coverband Demo](https:\u002F\u002Fgithub.com\u002Fcoverband-service\u002Fcoverband_demo)\n- JRuby is tested via CI against Rails 5 and 6\n\n# Contributing To Coverband\n\nIf you are working on adding features, PRs, or bugfixes to Coverband this section should help get you going.\n\n1. Fork it\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am 'Add some feature'`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Make sure all tests are passing (run `bundle install`, make sure Redis is running, and then execute `rake test`)\n6. Create new Pull Request\n\n### Tests & Benchmarks\n\nIf you submit a change please make sure the tests and benchmarks are passing.\n\n- run tests:\n  - `bundle exec rake`\n  - `BUNDLE_GEMFILE=Gemfile.rails7 bundle exec rake` (Same tests using rails 7 instead of 6)\n- view test coverage: `open coverage\u002Findex.html`\n- run the benchmarks before and after your change to see impact\n  - `rake benchmarks`\n  - run a single test by line number like rspec: `bundle exec m test\u002Fcoverband\u002Freporters\u002Fhtml_test.rb:29`\n  - run a single test file: `bundle exec ruby test\u002Fcoverband\u002Fcollectors\u002Ftranslation_tracker_test.rb`\n\n### Known Issues\n\n- **total fail** on front end code, for line for line coverage, because of the precompiled template step basically coverage doesn't work well for `erb`, `slim`, and the like.\n  - related it will try to report something, but the line numbers reported for `ERB` files are often off and aren't considered useful. I recommend filtering out .erb using the `config.ignore` option. The default configuration excludes these files\n  - **NOTE:** We now have file level coverage for view files, but don't support line level detail\n- **Coverage does NOT work when used alongside Scout APM Auto Instrumentation**\n  - In an environment that uses Scout's `AUTO_INSTRUMENT=true` (usually production or staging) it stops reporting any coverage, it will show one or two files that have been loaded at the start but everything else will show up as having 0% coverage\n  - Bug tracked here: https:\u002F\u002Fgithub.com\u002Fscoutapp\u002Fscout_apm_ruby\u002Fissues\u002F343\n- **Coverband, [Elastic APM](https:\u002F\u002Fgithub.com\u002Felastic\u002Fapm-agent-ruby) and resque**\n  - In an environment that uses the Elastic APM ruby agent, resque jobs will fail with `Transactions may not be nested. Already inside #\u003CElasticAPM::Transaction>` if the `elastic-apm` gem is loaded _before_ the `coverband` gem\n  - Put `coverage` ahead of `elastic-apm` in your Gemfile\n- **Bootsnap**, The methods used by [bootsnap do not support having coverage enabled](https:\u002F\u002Fgithub.com\u002FShopify\u002Fbootsnap\u002Fblob\u002Fmain\u002Flib\u002Fbootsnap\u002Fcompile_cache\u002Fiseq.rb#L87), so you can either have Coverband or bootsnap, but not both.  \n\n### Debugging Redis Store\n\nWhat files have been synced to Redis?\n\n`Coverband.configuration.store.covered_files`\n\nWhat is the coverage data in Redis?\n\n`Coverband.configuration.store.coverage`\n\n### Diagram\n\nA diagram of the code.\n\n![Visualization of this repo](https:\u002F\u002Fraw.githubusercontent.com\u002Fdanmayer\u002Fcoverband\u002Fdiagram\u002Fdiagram.svg)\n\n## Logo\n\nThe Coverband logo was created by [Dave Woodall](http:\u002F\u002Fdavewoodall.com). Thanks Dave!\n\n# License\n\nThis is a MIT License project...\nSee the file [LICENSE](LICENSE) for copying permission.\n","Coverband 是一个用于收集和报告 Ruby 生产环境代码覆盖率的工具，它能够统计每行代码被执行的次数。该项目的核心功能包括低性能开销的数据收集、简易配置以及对所有标准代码执行路径（如Web请求、定时任务、后台作业等）的支持。此外，Coverband 提供了直观易懂的报告，并且可以通过Rack中间件或手动配置灵活集成到应用中。它特别适合需要深入了解实际生产环境中哪些代码被频繁使用或未被使用的场景，帮助企业优化代码质量和维护效率。",2,"2026-06-11 03:15:08","top_language"]