{"id":13878352,"url":"https://github.com/coderberry/whoop","last_synced_at":"2025-07-30T01:08:19.100Z","repository":{"id":59935625,"uuid":"540205966","full_name":"coderberry/whoop","owner":"coderberry","description":"Log your data (sql, json, text) to your console with built-in formatting and colorization for Ruby on Rails","archived":false,"fork":false,"pushed_at":"2024-05-16T20:09:39.000Z","size":6701,"stargazers_count":32,"open_issues_count":2,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-15T06:14:06.946Z","etag":null,"topics":["logging"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/coderberry.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"coderberry"}},"created_at":"2022-09-22T23:30:28.000Z","updated_at":"2025-01-16T22:29:58.000Z","dependencies_parsed_at":"2024-08-06T08:46:54.026Z","dependency_job_id":"ef183649-524e-4a04-a33c-4c92e0ee9134","html_url":"https://github.com/coderberry/whoop","commit_stats":{"total_commits":22,"total_committers":1,"mean_commits":22.0,"dds":0.0,"last_synced_commit":"91e219a1d99986d897cf1609536ae4be3aed15d8"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coderberry%2Fwhoop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coderberry%2Fwhoop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coderberry%2Fwhoop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coderberry%2Fwhoop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/coderberry","download_url":"https://codeload.github.com/coderberry/whoop/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249016641,"owners_count":21198833,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["logging"],"created_at":"2024-08-06T08:01:47.062Z","updated_at":"2025-04-15T06:14:13.047Z","avatar_url":"https://github.com/coderberry.png","language":"Ruby","funding_links":["https://github.com/sponsors/coderberry"],"categories":["Ruby"],"sub_categories":[],"readme":"# Whoop\n\n[![Gem Version](https://badge.fury.io/rb/whoop.svg)](https://badge.fury.io/rb/whoop)\n[![Contribute](https://img.shields.io/badge/Contribute%20with-Gitpod-908a85?logo=gitpod)](https://gitpod.io/#https://github.com/coderberry/whoop)\n[![Maintainability](https://api.codeclimate.com/v1/badges/1ffd27fe59383a4ff52b/maintainability)](https://codeclimate.com/github/coderberry/whoop/maintainability)\n[![codecov](https://codecov.io/gh/coderberry/whoop/branch/main/graph/badge.svg?token=E906B6SEKD)](https://codecov.io/gh/coderberry/whoop)\n[![Tests](https://github.com/coderberry/whoop/actions/workflows/tests.yml/badge.svg)](https://github.com/coderberry/whoop/actions/workflows/tests.yml)\n[![CodeQL](https://github.com/coderberry/whoop/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/coderberry/whoop/actions/workflows/codeql-analysis.yml)\n[![StandardRB](https://github.com/coderberry/whoop/actions/workflows/standardrb.yml/badge.svg)](https://github.com/coderberry/whoop/actions/workflows/standardrb.yml)\n[![GEM Version](https://img.shields.io/gem/v/whoop?color=168AFE\u0026include_prereleases\u0026logo=ruby\u0026logoColor=FE1616)](https://rubygems.org/gems/whoop)\n[![GEM Downloads](https://img.shields.io/gem/dt/whoop?color=168AFE\u0026logo=ruby\u0026logoColor=FE1616)](https://rubygems.org/gems/whoop)\n[![Ruby Style](https://img.shields.io/badge/style-standard-168AFE?logo=ruby\u0026logoColor=FE1616)](https://github.com/testdouble/standard)\n[![Twitter Follow](https://img.shields.io/twitter/follow/coderberry?logo=twitter\u0026style=social)](https://twitter.com/coderberry)\n\nWhoop is a Ruby logging library with built-in formatting and colorization.\n\nTo try **whoop** within your browser, visit the [whoop playground](https://replit.com/@coderberry/whoop-playground).\n\n## Installation\n\nInstall the gem and add to the application's Gemfile by executing:\n\n    $ bundle add whoop\n\nIf bundler is not being used to manage dependencies, install the gem by executing:\n\n    $ gem install whoop\n\n## Configuration\n\nYou can configure the gem for you Rails app by adding an an initializer:\n\n```ruby\n# config/initializers/whoop.rb\nWhoop.setup do |config|\n  config.logger = ActiveSupport::Logger.new(\"log/debug.log\")\n  # config.logger = ActiveSupport::Logger.new(\"log/#{Rails.env}.log\")\n  # config.logger = ActiveSupport::Logger.new($stdout)\n  # config.logger = SemanticLogger[\"WHOOP\"]\n  # config.logger = nil # uses `puts`\n\n  config.level = :debug\n  # config.level = :info\n  # config.level = :warn\n  # config.level = :error\nend\n```\n\n## Usage\n\nThe `whoop` method is accessible from any object. See specs for more examples.\n\n```ruby\nwhoop \"Hello, World!\"\n```\n\nYou can pass any options into the `whoop` method to change the output.\n\n- `label` (first argument) - Either the object or title if a block is passed (see below)\n- `pattern` - String character to use for the line (default is `-`)\n- `count` - the number of times to repeat the pattern per line (e.g. 80)\n- `color` - the color to use for the line (e.g. :red)\n- `format` - the format to use for the message (one of `:json`, `:sql`, `:plain`, `:pretty`)\n- `caller_depth` - the depth of the caller to use for the source (default: 0)\n- `explain` - whether to run `EXPLAIN` on the SQL query (default: false)\n- `context` - a hash of key/value pairs to include in the output\n- `tags` - an array of tags to include in the output\n\n## Examples\n\n```ruby\nwhoop \"Hello\"\n\n# log/debug.log\n# ┏--------------------------------------------------------------------------------\n# ┆ timestamp: 2022-09-26 14:28:06 -0600\n# ┆ source: /spec/whoop_spec.rb:12\n#\n# Hello\n# \n# ┗--------------------------------------------------------------------------------\n```\n\n```ruby\nwhoop(\"My Label\", color: :green) { \"Hello\" }\n\n# log/debug.log (the colors don't appear in markdown)\n# ┏------------------------------------ My Label ------------------------------------\n# ┆ timestamp: 2022-09-26 14:28:06 -0600\n# ┆ source: /spec/whoop_spec.rb:26\n#\n# Hello\n# \n# ┗--------------------------------------------------------------------------------\n```\n\n```ruby\nwhoop({hello: \"world\"}, format: :json, color: false)\n\n# ┏--------------------------------------------------------------------------------\n# ┆ timestamp: 2022-09-26 14:28:06 -0600\n# ┆ source: /spec/whoop_spec.rb:39\n#\n# {\n#   \"hello\": \"world\"\n# }\n# \n# ┗--------------------------------------------------------------------------------\n```\n\n```ruby\nuser = User.first # or some object\nwhoop(user, format: :pretty)\n\n# ┏--------------------------------------------------------------------------------\n# ┆ timestamp: 2022-09-26 14:28:06 -0600\n# ┆ source: /spec/whoop_spec.rb:39\n#\n# User {\n#         :id =\u003e 1,\n#       :name =\u003e \"Eric\",\n#   :location =\u003e \"Utah\"\n# }\n# \n# ┗--------------------------------------------------------------------------------\n```\n\n```ruby\nwhoop(\"This message includes context\", color: false, context: {user: \"Eric\", ip_address: \"127.0.0.1\"})\n\n# ┏--------------------------------------------------------------------------------\n# ┆ timestamp: 2022-09-26 14:28:06 -0600\n# ┆ source: /spec/whoop_spec.rb:39\n# ┆ user: Eric\n# ┆ ip_address: 127.0.0.1\n#\n# This message includes context\n# \n# ┗--------------------------------------------------------------------------------\n```\n\n```ruby\nsql = 'SELECT emp_id, first_name,last_name,dept_id,mgr_id, ' +\n      'WIDTH_BUCKET(department_id,20,40,10) \"Exists in Dept\" ' +\n      'FROM emp WHERE mgr_id \u003c 300 ORDER BY \"Exists in Dept\"'\n\nwhoop(sql, format: :sql)\n\n# ┏--------------------------------------------------------------------------------\n# ┆ timestamp: 2022-09-26 14:28:06 -0600\n# ┆ source: /spec/whoop_spec.rb:52\n#\n# SELECT\n#     emp_id\n#     ,first_name\n#     ,last_name\n#     ,dept_id\n#     ,mgr_id\n#     ,WIDTH_BUCKET (\n#       department_id\n#       ,20\n#       ,40\n#       ,10\n#     ) \"Exists in Dept\"\n#   FROM\n#     emp\n#   WHERE\n#     mgr_id \u003c 300\n#   ORDER BY\n#     \"Exists in Dept\"\n# \n# ┗--------------------------------------------------------------------------------\n```\n\n#### Auto-explain SQL queries\n\nIn addition to formatting the SQL query, you can also ask whoop to perform an\n`explain` on the query by using the `explain: true` argument.\n\nExample (using the Example 1 sample plan from explain.dalibo.com):\n\n```ruby\nsql = \u003c\u003c~SQL\n    SELECT rel_users_exams.user_username AS rel_users_exams_user_username,\n             rel_users_exams.exam_id AS rel_users_exams_exam_id,\n             rel_users_exams.started_at AS rel_users_exams_started_at,\n             rel_users_exams.finished_at AS rel_users_exams_finished_at,\n             exam_1.id AS exam_1_id,\n             exam_1.title AS exam_1_title,\n             exam_1.date_from AS exam_1_date_from,\n             exam_1.date_to AS exam_1_date_to,\n             exam_1.created AS exam_1_created,\n             exam_1.created_by_ AS exam_1_created_by_,\n             exam_1.duration AS exam_1_duration,\n             exam_1.success_threshold AS exam_1_success_threshold,\n             exam_1.published AS exam_1_published\n    FROM rel_users_exams LEFT OUTER\n    JOIN exam AS exam_1\n        ON exam_1.id = rel_users_exams.exam_id\n    WHERE 1 = rel_users_exams.exam_id;\nSQL\n\nwhoop(\"SQL with Explain\", format: :sql, explain: true) { sql }\n\n# ┏-------------------------------- SQL with Explain --------------------------------\n# ┆ timestamp: 2022-09-26 14:50:11 -0600\n# ┆ source: (irb):23:in `\u003ctop (required)\u003e'\n#\n# sql:\n#\n# SELECT\n#     rel_users_exams.user_username AS rel_users_exams_user_username\n#     ,rel_users_exams.exam_id AS rel_users_exams_exam_id\n#     ,rel_users_exams.started_at AS rel_users_exams_started_at\n#     ,rel_users_exams.finished_at AS rel_users_exams_finished_at\n#     ,exam_1.id AS exam_1_id\n#     ,exam_1.title AS exam_1_title\n#     ,exam_1.date_from AS exam_1_date_from\n#     ,exam_1.date_to AS exam_1_date_to\n#     ,exam_1.created AS exam_1_created\n#     ,exam_1.created_by_ AS exam_1_created_by_\n#     ,exam_1.duration AS exam_1_duration\n#     ,exam_1.success_threshold AS exam_1_success_threshold\n#     ,exam_1.published AS exam_1_published\n#   FROM\n#     rel_users_exams LEFT OUTER JOIN exam AS exam_1\n#       ON exam_1.id = rel_users_exams.exam_id\n#   WHERE\n#     1 = rel_users_exams.exam_id\n# ;\n#\n# query plan:\n#\n# Nested Loop Left Join  (cost=11.95..28.52 rows=5 width=157) (actual time=0.010..0.010 rows=0 loops=1)\n#   Output: rel_users_exams.user_username, rel_users_exams.exam_id, rel_users_exams.started_at, rel_users_exams.finished_at, exam_1.id, exam_1.title, exam_1.date_from, exam_1.date_to, exam_1.created, exam_1.created_by_, exam_1.duration, exam_1.success_threshold, exam_1.published\n#   Inner Unique: true\n#   Join Filter: (exam_1.id = rel_users_exams.exam_id)\n#   Buffers: shared hit=1\n#   -\u003e  Bitmap Heap Scan on public.rel_users_exams  (cost=11.80..20.27 rows=5 width=52) (actual time=0.009..0.009 rows=0 loops=1)\n#         Output: rel_users_exams.user_username, rel_users_exams.exam_id, rel_users_exams.started_at, rel_users_exams.finished_at\n#         Recheck Cond: (1 = rel_users_exams.exam_id)\n#         Buffers: shared hit=1\n#         -\u003e  Bitmap Index Scan on rel_users_exams_pkey  (cost=0.00..11.80 rows=5 width=0) (actual time=0.005..0.005 rows=0 loops=1)\n#               Index Cond: (1 = rel_users_exams.exam_id)\n#               Buffers: shared hit=1\n#   -\u003e  Materialize  (cost=0.15..8.17 rows=1 width=105) (never executed)\n#         Output: exam_1.id, exam_1.title, exam_1.date_from, exam_1.date_to, exam_1.created, exam_1.created_by_, exam_1.duration, exam_1.success_threshold, exam_1.published\n#         -\u003e  Index Scan using exam_pkey on public.exam exam_1  (cost=0.15..8.17 rows=1 width=105) (never executed)\n#               Output: exam_1.id, exam_1.title, exam_1.date_from, exam_1.date_to, exam_1.created, exam_1.created_by_, exam_1.duration,\n# exam_1.success_threshold, exam_1.published\n#               Index Cond: (exam_1.id = 1)\n# Planning Time: 1.110 ms\n# Execution Time: 0.170 ms\n# \n# ┗--------------------------------------------------------------------------------\n```\n\n\n## Development\n\nAfter 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.\n\nTo 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 the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at https://github.com/coderberry/whoop. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/coderberry/whoop/blob/main/CODE_OF_CONDUCT.md).\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).\n\n## Code of Conduct\n\nEveryone interacting in the Whoop project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/coderberry/whoop/blob/main/CODE_OF_CONDUCT.md).\n\n## Attribution\n\nThis project is maintained by [Eric Berry](https://linktr.ee/coderberry).\n\nThis gem is based on the [wrapped_print](https://github.com/igorkasyanchuk/wrapped_print) gem by [Igor Kasyanchuk](https://www.railsjazz.com/).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoderberry%2Fwhoop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcoderberry%2Fwhoop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoderberry%2Fwhoop/lists"}