{"id":22931391,"url":"https://github.com/errm/promenade","last_synced_at":"2025-04-09T20:10:10.636Z","repository":{"id":37458491,"uuid":"139450199","full_name":"errm/promenade","owner":"errm","description":" Promenade is a libary to simplify instrumenting Ruby applications with prometheus.","archived":false,"fork":false,"pushed_at":"2024-12-10T22:56:48.000Z","size":385,"stargazers_count":17,"open_issues_count":6,"forks_count":5,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-09T20:10:03.498Z","etag":null,"topics":[],"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/errm.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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}},"created_at":"2018-07-02T13:50:47.000Z","updated_at":"2024-10-12T12:03:10.000Z","dependencies_parsed_at":"2024-01-24T17:51:48.980Z","dependency_job_id":"77866f1a-225b-44be-8681-0091d287f804","html_url":"https://github.com/errm/promenade","commit_stats":{"total_commits":200,"total_committers":10,"mean_commits":20.0,"dds":0.52,"last_synced_commit":"6cfd879a2282a1d0ea916c4b7d323f451288f766"},"previous_names":[],"tags_count":32,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/errm%2Fpromenade","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/errm%2Fpromenade/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/errm%2Fpromenade/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/errm%2Fpromenade/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/errm","download_url":"https://codeload.github.com/errm/promenade/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248103871,"owners_count":21048245,"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":[],"created_at":"2024-12-14T10:38:57.187Z","updated_at":"2025-04-09T20:10:10.608Z","avatar_url":"https://github.com/errm.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Promenade\n\n[![CI](https://github.com/errm/promenade/actions/workflows/ci.yaml/badge.svg)](https://github.com/errm/promenade/actions/workflows/ci.yaml)\n[![Gem Version](https://badge.fury.io/rb/promenade.svg)](https://badge.fury.io/rb/promenade)\n[![codecov](https://codecov.io/github/errm/promenade/graph/badge.svg?token=Xreh8NR1nh)](https://codecov.io/github/errm/promenade)\n\nPromenade is a library to simplify instrumenting Ruby applications with Prometheus.\n\nIt is currently under development.\n\n## Usage\n\nAdd promenade to your Gemfle:\n\n```\ngem \"promenade\"\n```\n\n### Built in instrumentation\n\nPromenade includes some built in instrumentation that can be used by requiring it (for example in an initializer).\n\nCurrently there is support for [ruby-kafka](https://github.com/zendesk/ruby-kafka), but I plan to support other things soon.\n\n```\n# Instrument the ruby-kafka libary\nrequire \"promenade/kafka\"\n```\n\n### Instrumentation DSL\n\nPromenade makes recording Prometheus metrics from your own code a little simpler with a DSL of sorts.\n\n`Promenade` includes some methods for defining your own metrics, and a metric method you can use to record your metrics.\n\n#### Counter\n\nA counter is a metric that exposes a sum or tally of things.\n\n```ruby\nclass WidgetService\n  Promenade.counter :widgets_created do\n    doc \"Records how many widgets are created\"\n  end\n\n  def create\n    # Widget creation code :)\n    Promenade.metric(:widgets_created).increment\n\n    # You can also add extra labels as you set increment counters\n    Promenade.metric(:widgets_created).increment({ type: \"guinness\" })\n  end\n\n  def batch_create\n    You can increment by more than 1 at a time if you need\n    Promenade.metric(:widgets_created).increment({ type: \"guinness\" }, 100)\n  end\nend\n```\n\n#### Gauge\n\nA gauge is a metric that exposes an instantaneous value or some snapshot of a changing value.\n\n```ruby\nclass Thermometer\n  Promenade.gauge :room_temperature_celsius do\n    doc \"Records room temprature\"\n  end\n\n  def take_mesurements\n    Promenade.metric(:room_temperature_celsius).set({ room: \"lounge\" }, 22.3)\n    Promenade.metric(:room_temperature_celsius).set({ room: \"kitchen\" }, 25.45)\n    Promenade.metric(:room_temperature_celsius).set({ room: \"broom_cupboard\" }, 15.37)\n  end\nend\n```\n\n#### Histogram\n\nA histogram samples observations (usually things like request durations or\nresponse sizes) and counts them in configurable buckets. It also provides a sum\nof all observed values.\n\n```ruby\nclass Calculator\n  Promenade.histogram :calculator_time_taken do\n    doc \"Records how long it takes to do the adding\"\n    # promenade also has some bucket presets like :network and :memory for common usecases\n    buckets [0.25, 0.5, 1, 2, 4]\n  end\n\n  def add_up\n    timing = Benchmark.realtime do\n      # Some time consuming addition\n    end\n\n    Promenade.metric(:calculator_time_taken).observe({ operation: \"addition\"}, timing)\n  end\nend\n```\n\n#### Summary\n\nSummary is similar to a histogram, but for when you just care about percentile values. Often useful for timings.\n\n```ruby\nclass ApiClient\n  Promenade.summary :api_client_http_timing do\n    doc \"record how long requests to the api are taking\"\n  end\n\n  def get_users\n    timing = Benchmark.realtime do\n      # Makes a network call\n    end\n\n    Promenade.metric(:api_client_http_timing).observe({ method: \"get\", path: \"/api/v1/users\" }, timing)\n  end\nend\n```\n\n### Exporter\n\nBecause promenade is based on prometheus-client you can add the `Prometheus::Client::Rack::Exporter` middleware to your rack middleware stack to expose metrics.\n\nThere is also a stand alone exporter that can be run with the `promenade` command.\n\nThis is ideal if you are worried about accidentally exposing your metrics, are concerned about the performance impact prometheus scrapes might have on your application, or for applications without a web server (like background processing jobs). It does mean that you have another process to manage on your server though 🤷.\n\nThe exporter runs by default on port `9394` and the metrics are available at the standard path of `/metrics`, the stand-alone exporter is configured to use gzip.\n\n\n### Rails Middleware\n\nPromenade provides custom Rack middleware to track HTTP response times for requests in your Rails application.\n\nThis was originally inspired by [prometheus-client-mmap](https://gitlab.com/gitlab-org/prometheus-client-mmap/-/blob/master/lib/prometheus/client/rack/collector.rb).\n\n**This middleware is automatically added to your Rack stack if your application is a Ruby on Rails app.**\n\nWe recommend you add the middleware after `ActionDispatch::ShowExceptions` in your stack, so you can accurately record the controller and action where an exception was raised.\n\nIf you want to change the position, or customise the labels and exception handling behaviour, simply remove the middleware from the stack and re-insert it with your own preferences.\n\n``` ruby\nRails.application.middleware.delete(Promenade::Client::Rack::Collector)\nRails.application.middleware.insert_after(Rails::Rack::Logger, Promenade::Client::Rack::Collector)\n```\n\n#### Customising the labels recorded for each request\n\nIf you would like to collect different labels with each request, you may do so by customising the middleware installation:\n\n``` ruby\nlabel_builder = Proc.new do |env|\n  {\n    method: env[\"REQUEST_METHOD\"].to_s.downcase,\n    host: env[\"HTTP_HOST\"].to_s,\n    controller: env.dig(\"action_dispatch.request.parameters\", \"controller\") || \"unknown\",\n    action: env.dig(\"action_dispatch.request.parameters\", \"action\") || \"unknown\"\n  }\nend\nRails.application.config.middleware.insert_after ActionDispatch::ShowExceptions,\n        Promenade::Client::Rack::Collector\n        label_builder: label_builder\n```\n\n#### Customising how the middleware handles exceptions\n\nThe default implementation will capture exceptions, count the execption class name (e.g. `\"StandardError\"`), and then re-raise the exception.\n\nIf you would like to customise this behaviour, you may do so by customising the middleware installation:\n\n``` ruby\nexception_handler = Proc.new do |exception, exception_counter, env_hash, request_duration_seconds|\n  # This simple example just re-raises the execption\n  raise exception\nend\nRails.application.config.middleware.insert_after ActionDispatch::ShowExceptions,\n        Promenade::Client::Rack::Collector\n        exception_handler: exception_handler\n```\n\n#### Customising the histogram buckets\n\nThe default buckets cover a range of latencies from 5 ms to 10s see [Promenade::Configuration::DEFAULT_RACK_LATENCY_BUCKETS](https://github.com/errm/promenade/blob/ea7eb54c04257770a601b7e28b3e13db5d2430bb/lib/promenade/configuration.rb#L5). This is intended to capture the typical range of latencies for a web application. However, this might not be suitable for your Service-Level Agreements (SLAs), and other bucket size intervals may be required (see [histogram bins](https://en.wikipedia.org/wiki/Histogram#Number_of_bins_and_width)).\n\nIf you would like to customise the histogram buckets, you can do so by configuring Promenade in an initializer:\n\n```ruby\n# config/initializers/promenade.rb\n\nPromenade.configure do |config|\n  config.rack_latency_buckets = [0.25, 0.350, 0.5, 1, 1.5, 2.5, 5, 10, 15, 19]\nend\n```\n\n### Configuration\n\nIf you are using rails it should load a railtie and configure promenade.\n\nIf are not using rails you should call `Promenade.setup` after your environment has loaded.\n\nIn a typical development environment there should be nothing for you to do. Promenade stores its state files in `tmp/promenade` and will create that directory if it does not exist.\n\nIn a production environment you should try to store the state files on tmpfs for performance, you can configure the path that promenade will write to by setting the `PROMETHEUS_MULTIPROC_DIR` environment variable.\n\nIf you are running the stand-alone exporter, you may also set the `PORT` environment variable to bind to a port other than the default (`9394`).\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 tags, 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/errm/promenade.\n\nThis project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.\n\n## Acknowledgements\n\nThe original code for the Rack middleware collector class was copied from [Prometheus Client MMap](https://gitlab.com/gitlab-org/prometheus-client-mmap/-/blob/master/lib/prometheus/client/rack/collector.rb).\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 Promenade project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/promenade/blob/master/CODE_OF_CONDUCT.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ferrm%2Fpromenade","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ferrm%2Fpromenade","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ferrm%2Fpromenade/lists"}