{"id":19294651,"url":"https://github.com/moesif/moesif-rack","last_synced_at":"2025-11-11T18:38:47.987Z","repository":{"id":16294170,"uuid":"73112693","full_name":"Moesif/moesif-rack","owner":"Moesif","description":"Moesif Middleware for Ruby on Rails/Rack, for API Monitoring, Analytics, and Monetization.","archived":false,"fork":false,"pushed_at":"2024-09-23T14:40:57.000Z","size":209,"stargazers_count":7,"open_issues_count":0,"forks_count":8,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-01-25T12:41:36.885Z","etag":null,"topics":["analytics","api-analytics","api-logs","api-management","api-monetization","api-monitoring","logger","logging","logging-library","logginginterceptor","middlewares","monitoring","observability","rack-middleware","ruby","ruby-on-rails","usage-based-billing"],"latest_commit_sha":null,"homepage":"https://www.moesif.com","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Moesif.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2016-11-07T19:23:41.000Z","updated_at":"2024-12-21T23:11:05.000Z","dependencies_parsed_at":"2023-02-18T10:32:13.160Z","dependency_job_id":"339da31f-d5a1-48e4-b39e-12d722d2e3a9","html_url":"https://github.com/Moesif/moesif-rack","commit_stats":{"total_commits":102,"total_committers":12,"mean_commits":8.5,"dds":0.7549019607843137,"last_synced_commit":"4ab439fb6f1d4302101e94ac8bd0697178328f65"},"previous_names":[],"tags_count":43,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Moesif%2Fmoesif-rack","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Moesif%2Fmoesif-rack/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Moesif%2Fmoesif-rack/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Moesif%2Fmoesif-rack/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Moesif","download_url":"https://codeload.github.com/Moesif/moesif-rack/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238059009,"owners_count":19409607,"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":["analytics","api-analytics","api-logs","api-management","api-monetization","api-monitoring","logger","logging","logging-library","logginginterceptor","middlewares","monitoring","observability","rack-middleware","ruby","ruby-on-rails","usage-based-billing"],"created_at":"2024-11-09T22:39:06.530Z","updated_at":"2025-11-11T18:38:47.943Z","avatar_url":"https://github.com/Moesif.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Moesif Middleware for Ruby on Rails and Rack\nby [Moesif](https://moesif.com), the [API analytics](https://www.moesif.com/features/api-analytics) and [API monetization](https://www.moesif.com/solutions/metered-api-billing) platform.\n\n[![Built For rack][ico-built-for]][link-built-for]\n[![Latest Version][ico-version]][link-package]\n[![Total Downloads][ico-downloads]][link-downloads]\n[![Software License][ico-license]][link-license]\n[![Source Code][ico-source]][link-source]\n\nMoesif Rack Middleware automatically logs incoming and outgoing API calls \nand sends them to [Moesif](https://www.moesif.com) for API analytics and monitoring.\nThis middleware allows you to integrate Moesif's API analytics and \nAPI monetization features into your Ruby applications with minimal configuration. The middleware \nsupports Ruby on Rails, Grape, and other Ruby frameworks built on Rack.\n\n\u003e If you're new to Moesif, see [our Getting Started](https://www.moesif.com/docs/) resources to quickly get up and running.\n\n## Prerequisites\nBefore using this middleware, make sure you have the following:\n\n- [An active Moesif account](https://moesif.com/wrap)\n- [A Moesif Application ID](#get-your-moesif-application-id)\n\n### Get Your Moesif Application ID\nAfter you log into [Moesif Portal](https://www.moesif.com/wrap), you can get your Moesif Application ID during the onboarding steps. You can always access the Application ID any time by following these steps from Moesif Portal after logging in:\n\n1. Select the account icon to bring up the settings menu.\n2. Select **Installation** or **API Keys**.\n3. Copy your Moesif Application ID from the **Collector Application ID** field.\n\u003cimg class=\"lazyload blur-up\" src=\"images/app_id.png\" width=\"700\" alt=\"Accessing the settings menu in Moesif Portal\"\u003e\n\n## Install the Middleware\nInstall the Moesif gem:\n\n```bash\ngem install moesif_rack\n```\n\nIf you're using Bundler, add the gem to your `Gemfile`:\n\n```ruby\ngem 'moesif_rack'\n```\n\nThen run `bundle install`.\n\n## Configure the Middleware\nSee the available [configuration options](#configuration-options) to learn how to configure the middleware for your use case.\n\n## How to use\n\n### 1. Enter Moesif Application ID\n\nCreate a hash containing `application_id` and specify your [Moesif Application ID](#get-your-moesif-application-id) as its value. This hash also contains other [options](#configuration-options) you may want to specify.\n\n```ruby\nmoesif_options = {\n  'application_id' =\u003e 'YOUR_MOESIF_APPLICATION_ID'\n}\n```\n\n### 2. Add the Middleware\n\n#### For Rails 5.0 or Newer\n\nUsing strings or symbols for middleware class names is deprecated for newer frameworks like Ruby 5.0. So we recommend \nthat you pass the class directly:\n\n```ruby\n  class Application \u003c Rails::Application\n    moesif_options = {\n      'application_id' =\u003e 'YOUR_MOESIF_APPLICATION_ID'\n    }\n\n    config.middleware.use MoesifRack::MoesifMiddleware, moesif_options\n  end\n```\n\n#### For Rails 4.0 and Other Frameworks\n\nFor most Rack-based frameworks including Rails 4.x or older, add the middleware `MoesifRack::MoesifMiddleware` within `config/application.rb`:\n\n```ruby\n  class Application \u003c Rails::Application\n    moesif_options = {\n      'application_id' =\u003e 'Your Moesif Application Id'\n    }\n\n    config.middleware.use \"MoesifRack::MoesifMiddleware\", moesif_options\n  end\n```\n\n#### For Grape API\n\nFor [Grape APIs](https://github.com/ruby-grape/grape), you can add the middleware after any custom parsers or formatters.\n\n```ruby\nmodule Acme\n  class Ping \u003c Grape::API\n    format :json\n\n    moesif_options = {\n      'application_id' =\u003e 'Your Moesif Application Id'\n    }\n\n    insert_after Grape::Middleware::Formatter, MoesifRack::MoesifMiddleware, moesif_options\n\n    get '/ping' do\n      { ping: 'pong' }\n    end\n  end\nend\n```\n\n#### Order of Middleware\n\nSince Moesif Rack is a logging middleware, the ordering of middleware matters.\n\nThe best place for `MoesifRack::MoesifMidleware` is near the top so it captures the data closest to the wire. \nBut remember to put it after any body parsers or authentication  middleware.\n\nTypically, right above the default logger of Rails app `Rails::Rack::Logger` is a good spot.\nIf you want to be as close as wire as possible, put it before `ActionDispatch::Static`.\n\nTo insert the Moesif middleware before `Rails::Rack::Logger`, you can use the `insert_before` method instead of \n`use`:\n\n```ruby\n  class Application \u003c Rails::Application\n    # snip\n\n    config.middleware.insert_before Rails::Rack::Logger, MoesifRack::MoesifMiddleware, moesif_options\n\n    # snip\n  end\n```\n\nIf you are using `Rack::Deflater` or other compression middleware, make sure to put the Moesif middleware after\nit so it can capture the uncompressed data.\n\nTo see your current list of middleware, execute this command:\n\n```bash\n  bin/rails middleware\n```\n### Optional: Capturing Outgoing API Calls\nIn addition to your own APIs, you can also start capturing calls out to third party services through by setting the [`capture_outgoing_requests`](#capture_outgoing_requests) option.\n\nFor configuration options specific to capturing outgoing API calls, see [Options For Outgoing API Calls](#options-for-outgoing-api-calls).\n\n## Troubleshoot\nFor a general troubleshooting guide that can help you solve common problems, see [Server Troubleshooting Guide](https://www.moesif.com/docs/troubleshooting/server-troubleshooting-guide/).\n\nOther troubleshooting supports:\n\n- [FAQ](https://www.moesif.com/docs/faq/)\n- [Moesif support email](mailto:support@moesif.com)\n\n## Repository Structure\n\n```\n.\n├── BUILDING.md\n├── Gemfile\n├── images/\n├── lib/\n├── LICENSE\n├── moesif_capture_outgoing/\n├── moesif_rack.gemspec\n├── Rakefile\n├── README.md\n└── test/\n```\n\n## Configuration Options\nThe following sections describe the available configuration options for this middleware. You have to set these options in a Ruby hash as key-value pairs. See the [examples](#examples) for better understanding.\n\n#### `application_id` (Required)\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    String\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nA string that [identifies your application in Moesif](#get-your-moesif-application-id).\n\n#### `api_version`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    String\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nOptional.\n\nUse to tag requests with the version of your API.\n\n\n#### `identify_user`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Return type\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eProc\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    String\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nOptional, but highly recommended.\n\nA `Proc` that takes `env`, `headers`, and `body` as arguments.\n\nReturns a string that represents the user ID used by your system. \n\nMoesif identifies users automatically. However, due to the differences arising from different frameworks and implementations, set this option to ensure user identification properly.\n\n\n```ruby\nmoesif_options['identify_user'] = Proc.new { |env, headers, body|\n\n  # Add your custom code that returns a string for user id\n  '12345'\n}\n```\n\n#### `identify_company`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Return type\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eProc\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    String\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nOptional.\n\nA `Proc` that takes `env`, `headers`, and `body` as arguments.\n\nReturns a string that represents the company ID for this event. This helps Moesif attribute requests to unique company.\n\n```ruby\n\nmoesif_options['identify_company'] = Proc.new { |env, headers, body|\n\n  # Add your custom code that returns a string for company id\n  '67890'\n}\n\n```\n\n#### `identify_session`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Return type\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eProc\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    String\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nOptional.\n\nA `Proc` that takes `env`, `headers`, and `body` as arguments.\n\nReturns a string that represents the session token for this event. \n\nSimilar to users and companies, Moesif tries to retrieve session tokens automatically. But if it doesn't work for your service, use this option to help identify sessions.\n\n```ruby\n\nmoesif_options['identify_session'] = Proc.new { |env, headers, body|\n    # Add your custom code that returns a string for session/API token\n    'XXXXXXXXX'\n}\n```\n\n#### `get_metadata`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Return type\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eProc\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eHash\u003c/code\u003e\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nOptional.\n\nA `Proc` that takes `env`, `headers`, and `body` as arguments.\n\nReturns a `Hash` that represents a JSON object. This allows you to attach any\nmetadata to this event.\n\n```ruby\n\nmoesif_options['get_metadata'] = Proc.new { |env, headers, body|\n  # Add your custom code that returns a dictionary\n  value = {\n      'datacenter'  =\u003e 'westus',\n      'deployment_version'  =\u003e 'v1.2.3'\n  }\n  value\n}\n```\n\n#### `mask_data`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Return type\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eProc\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eEventModel\u003c/code\u003e\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nOptional. \n\nA Proc that takes an `EventModel` as an argument and returns an `EventModel`.\n\nThis option allows you to modify headers or body of an event before sending the event to Moesif.\n\n```ruby\n\nmoesif_options['mask_data'] = Proc.new { |event_model|\n  # Add your custom code that returns a event_model after modifying any fields\n  event_model.response.body.password = nil\n  event_model\n}\n\n```\n\nFor more information and the spec of Moesif's event model, see the source code of [Moesif API library for Ruby](https://github.com/Moesif/moesifapi-ruby).\n\n#### `skip`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Return type\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eProc\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    Boolean\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nOptional.\n\nA `Proc` that takes `env`, `headers`, and `body` as arguments.\n\nReturns a boolean. Return `true` if you want to skip a particular event.\n\n```ruby\n\nmoesif_options['skip'] = Proc.new { |env, headers, body|\n  # Add your custom code that returns true to skip logging the API call\n  if env.key?(\"REQUEST_URI\") \n      # Skip probes to health page\n      env[\"REQUEST_URI\"].include? \"/health\"\n  else\n      false\n  end\n}\n\n```\n\n#### `debug`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Default\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    Boolean\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003efalse\u003c/code\u003e\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nOptional.\n\nIf `true`, the middleware prints out debug messages. In debug mode, the processing is not done in backend thread.\n\n#### `log_body`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Default\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    Boolean\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003etrue\u003c/code\u003e\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nOptional.\n\nIf `false`, doesn't log request and response body to Moesif.\n\n#### `batch_size`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Default\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eint\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003e200\u003c/code\u003e\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nOptional.\n\nThe maximum batch size when sending to Moesif.\n\n#### `batch_max_time`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Default\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eint\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003e2\u003c/code\u003e\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nOptional. \n\nThe maximum time in seconds to wait (approximately) before triggering flushing of the queue and sending to Moesif.\n\n#### `event_queue_size`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Default\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eint\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003e1000000\u003c/code\u003e\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nOptional.\n\nThe maximum number of events to hold in queue before sending to Moesif. \n\nIn case of network issues, the middleware may fail to connect or send event to Moesif. In those cases, the middleware skips adding new to event to queue to prevent memory overflow.\n\n### Options For Outgoing API Calls \nThe following options apply to outgoing API calls. These are calls you initiate using [`Net::HTTP`](https://ruby-doc.org/stdlib-2.6.3/libdoc/net/http/rdoc/Net/HTTP.html) package to third parties like Stripe or to your own services.\n\nSeveral options use request and response as input arguments. The request and response objects passed in are [`HTTPRequest`](https://www.rubydoc.info/stdlib/net/Net/HTTPRequest) request and [`HTTPResponse`](https://www.rubydoc.info/stdlib/net/Net/HTTPResponse) response objects.\n\n#### `capture_outgoing_requests`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Default\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    Boolean\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003efalse\u003c/code\u003e\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nSet to `true` to capture all outgoing API calls from your app.\n\n#### `identify_user_outgoing`\n\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Return type\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eProc\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    String\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nOptional, but highly recommended.\n\nA `Proc` that takes `env`, `headers`, and `body` as arguments.\n\nReturns a string that represents the user ID used by your system. \n\nMoesif identifies users automatically. However, due to the differences arising from different frameworks and implementations, set this option to ensure user identification properly.\n\n```ruby\n\nmoesif_options['identify_user_outgoing'] = Proc.new { |request, response|\n\n  # Add your custom code that returns a string for user id\n  '12345'\n}\n\n```\n\n#### `identify_company_outgoing`\n\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Return type\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eProc\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    String\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nOptional.\n\nA `Proc` that takes `env`, `headers`, and `body` as arguments.\n\nReturns a string that represents the company ID for this event. This helps Moesif attribute requests to unique company.\n\n\n```ruby\n\nmoesif_options['identify_company_outgoing'] = Proc.new { |request, response|\n\n  # Add your custom code that returns a string for company id\n  '67890'\n}\n\n```\n\n#### `get_metadata_outgoing`\n\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Return type\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eProc\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eHash\u003c/code\u003e\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nOptional.\n\nA `Proc` that takes `env`, `headers`, and `body` as arguments.\n\nReturns a `Hash` that represents a JSON object. This allows you to attach any\nmetadata to this event.\n\n\n```ruby\n\nmoesif_options['get_metadata_outgoing'] = Proc.new { |request, response|\n\n  # Add your custom code that returns a dictionary\n  value = {\n      'datacenter'  =\u003e 'westus',\n      'deployment_version'  =\u003e 'v1.2.3'\n  }\n  value\n}\n```\n\n#### `identify_session_outgoing`\n\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Return type\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eProc\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    String\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nOptional.\n\nA `Proc` that takes `env`, `headers`, and `body` as arguments.\n\nReturns a string that represents the session token for this event. \n\nSimilar to users and companies, Moesif tries to retrieve session tokens automatically. But if it doesn't work for your service, use this option to help identify sessions.\n\n```ruby\n\nmoesif_options['identify_session_outgoing'] = Proc.new { |request, response|\n\n    # Add your custom code that returns a string for session/API token\n    'XXXXXXXXX'\n}\n\n```\n\n#### `skip_outgoing`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Return type\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eProc\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    Boolean\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nOptional.\n\nA `Proc` that takes `env`, `headers`, and `body` as arguments.\n\nReturns a boolean. Return `true` if you want to skip a particular event.\n\n\n```ruby\n\nmoesif_options['skip_outgoing'] = Proc.new{ |request, response|\n\n  # Add your custom code that returns true to skip logging the API call\n  false\n}\n\n```\n\n#### `mask_data_outgoing`\n\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Return type\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eProc\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eEventModel\u003c/code\u003e\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nOptional. \n\nA Proc that takes an `EventModel` as an argument and returns an `EventModel`.\n\nThis option allows you to modify headers or body of an event before sending the event to Moesif.\n\n```ruby\n\nmoesif_options['mask_data_outgoing'] = Proc.new { |event_model|\n\n  # Add your custom code that returns a event_model after modifying any fields\n  event_model.response.body.password = nil\n  event_model\n}\n\n```\n\n### `log_body_outgoing`\n\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Default\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    Boolean\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003etrue\u003c/code\u003e\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nOptional.\n\nIf `false`, doesn't log request and response body to Moesif.\n\n## Examples\n\n- __[Moesif Rails 5 Example](https://github.com/Moesif/moesif-rails5-example)__: an example of Moesif with a Ruby on Rails 5 application\n- __[Moesif Rails 4 Example](https://github.com/Moesif/moesif-rails4-example)__: an example of Moesif with a Ruby on Rails 4 application\n- __[Moesif Rack Example](https://github.com/Moesif/moesif-rack-example)__: an example of Moesif in a Rack application\n\nThe following examples demonstrate how to add and update customer information.\n\n### Update a Single User\nTo create or update a [user](https://www.moesif.com/docs/getting-started/users/) profile in Moesif, use the `update_user()` method.\n\n```ruby\nmetadata = {\n  :email =\u003e 'john@acmeinc.com',\n  :first_name =\u003e 'John',\n  :last_name =\u003e 'Doe',\n  :title =\u003e 'Software Engineer',\n  :salesInfo =\u003e {\n      :stage =\u003e 'Customer',\n      :lifetime_value =\u003e 24000,\n      :accountOwner =\u003e 'mary@contoso.com',\n  }\n}\n\n# Campaign object is optional, but useful if you want to track ROI of acquisition channels\n# See https://www.moesif.com/docs/api#users for campaign schema\ncampaign = MoesifApi::CampaignModel.new()\ncampaign.utm_source = \"google\"\ncampaign.utm_medium = \"cpc\"\ncampaign.utm_campaign = \"adwords\"\ncampaign.utm_term = \"api+tooling\"\ncampaign.utm_content = \"landing\"\n\n# Only user_id is required.\n# metadata can be any custom object\nuser = MoesifApi::UserModel.new()\nuser.user_id = \"12345\"\nuser.company_id = \"67890\" # If set, associate user with a company object\nuser.campaign = campaign\nuser.metadata = metadata\n\nupdate_user = MoesifRack::MoesifMiddleware.new(@app, @options).update_user(user_model)\n```\nThe `metadata` field can contain any customer demographic or other info you want to store. Moesif only requires the `user_id` field.\n\nFor more information, see the function documentation in [Moesif Ruby API reference](https://www.moesif.com/docs/api?ruby#update-a-user).\n\n### Update Users in Batch\nTo update a list of [users](https://www.moesif.com/docs/getting-started/users/) in one batch, use the `update_users_batch()` method.\n\n```ruby\nusers = []\n\nmetadata = {\n  :email =\u003e 'john@acmeinc.com',\n  :first_name =\u003e 'John',\n  :last_name =\u003e 'Doe',\n  :title =\u003e 'Software Engineer',\n  :salesInfo =\u003e {\n      :stage =\u003e 'Customer',\n      :lifetime_value =\u003e 24000,\n      :accountOwner =\u003e 'mary@contoso.com',\n  }\n}\n\n# Campaign object is optional, but useful if you want to track ROI of acquisition channels\n# See https://www.moesif.com/docs/api#users for campaign schema\ncampaign = MoesifApi::CampaignModel.new()\ncampaign.utm_source = \"google\"\ncampaign.utm_medium = \"cpc\"\ncampaign.utm_campaign = \"adwords\"\ncampaign.utm_term = \"api+tooling\"\ncampaign.utm_content = \"landing\"\n\n# Only user_id is required.\n# metadata can be any custom object\nuser = MoesifApi::UserModel.new()\nuser.user_id = \"12345\"\nuser.company_id = \"67890\" # If set, associate user with a company object\nuser.campaign = campaign\nuser.metadata = metadata\n\nusers \u003c\u003c user\n\nresponse = MoesifRack::MoesifMiddleware.new(@app, @options).update_users_batch(users)\n```\n\nThe `metadata` field can contain any customer demographic or other info you want to store. Moesif only requires the `user_id` field. This method is a convenient helper that calls the Moesif API lib.\n\nFor more information, see the function documentation in [Moesif Ruby API reference](https://www.moesif.com/docs/api?ruby#update-users-in-batch).\n\n### Update a Single Company\nTo update a single [company](https://www.moesif.com/docs/getting-started/companies/), use the `update_company()` method.\n\n```ruby\nmetadata = {\n  :org_name =\u003e 'Acme, Inc',\n  :plan_name =\u003e 'Free',\n  :deal_stage =\u003e 'Lead',\n  :mrr =\u003e 24000,\n  :demographics =\u003e {\n      :alexa_ranking =\u003e 500000,\n      :employee_count =\u003e 47\n  }\n}\n\n# Campaign object is optional, but useful if you want to track ROI of acquisition channels\n# See https://www.moesif.com/docs/api#update-a-company for campaign schema\ncampaign = MoesifApi::CampaignModel.new()\ncampaign.utm_source = \"google\"\ncampaign.utm_medium = \"cpc\"\ncampaign.utm_campaign = \"adwords\"\ncampaign.utm_term = \"api+tooling\"\ncampaign.utm_content = \"landing\"\n\n# Only company_id is required.\n# metadata can be any custom object\ncompany = MoesifApi::CompanyModel.new()\ncompany.company_id = \"67890\"\ncompany.company_domain = \"acmeinc.com\" # If domain is set, Moesif will enrich your profiles with publicly available info \ncompany.campaign = campaign\ncompany.metadata = metadata\n\nupdate_company = MoesifRack::MoesifMiddleware.new(@app, @options).update_company(company_model)\n```\n\nThe `metadata` field can contain any customer demographic or other info you want to store. Moesif only requires the `company_id` field. This method is a convenient helper that calls the Moesif API lib.\n\nFor more information, see the function documentation in [Moesif Ruby API reference](https://www.moesif.com/docs/api?ruby#update-a-company).\n\n### Update Companies in Batch\nTo update a list of [companies](https://www.moesif.com/docs/getting-started/companies/) in one batch, use the `update_companies_batch()` method.\n\n```ruby\ncompanies = []\n\nmetadata = {\n  :org_name =\u003e 'Acme, Inc',\n  :plan_name =\u003e 'Free',\n  :deal_stage =\u003e 'Lead',\n  :mrr =\u003e 24000,\n  :demographics =\u003e {\n      :alexa_ranking =\u003e 500000,\n      :employee_count =\u003e 47\n  }\n}\n\n# Campaign object is optional, but useful if you want to track ROI of acquisition channels\n# See https://www.moesif.com/docs/api#update-a-company for campaign schema\ncampaign = MoesifApi::CampaignModel.new()\ncampaign.utm_source = \"google\"\ncampaign.utm_medium = \"cpc\"\ncampaign.utm_campaign = \"adwords\"\ncampaign.utm_term = \"api+tooling\"\ncampaign.utm_content = \"landing\"\n\n# Only company_id is required.\n# metadata can be any custom object\ncompany = MoesifApi::CompanyModel.new()\ncompany.company_id = \"67890\"\ncompany.company_domain = \"acmeinc.com\" # If domain is set, Moesif will enrich your profiles with publicly available info \ncompany.campaign = campaign\ncompany.metadata = metadata\n\ncompanies \u003c\u003c company\nresponse = MoesifRack::MoesifMiddleware.new(@app, @options).update_companies_batch(companies)\n```\n\nThe `metadata` field can contain any customer demographic or other info you want to store. Moesif only requires the `company_id` field. This method is a convenient helper that calls the Moesif API lib.\n\nFor more information, see the function documentation in [Moesif Ruby API reference](https://www.moesif.com/docs/api?ruby#update-companies-in-batch).\n\n## How to Test\n\n1. Manually clone this repository.\n2. From your terminal, navigate to the root directory of the middleware.\n3. Run `gem install moesif_rack`.\n4. Add your [Moesif Application ID](#get-your-moesif-application-id) to `test/moesif_rack_test.rb`.\n5. Run `ruby test/moesif_rack_test.rb`.\n6. Then run `ruby -I test test/moesif_rack_test.rb -n test_capture_outgoing` to test capturing outgoing API calls from your app to third parties like Stripe, Github or to your own dependencies.\n\n## Explore Other Integrations\n\nExplore other integration options from Moesif:\n\n- [Server integration options documentation](https://www.moesif.com/docs/server-integration//)\n- [Client integration options documentation](https://www.moesif.com/docs/client-integration/)\n\n[ico-built-for]: https://img.shields.io/badge/built%20for-rack-blue.svg\n[ico-version]: https://img.shields.io/gem/v/moesif_rack.svg\n[ico-downloads]: https://img.shields.io/gem/dt/moesif_rack.svg\n[ico-license]: https://img.shields.io/badge/License-Apache%202.0-green.svg\n[ico-source]: https://img.shields.io/github/last-commit/moesif/moesif-rack.svg?style=social\n\n[link-built-for]: https://github.com/rack/rack\n[link-package]: https://rubygems.org/gems/moesif_rack\n[link-downloads]: https://rubygems.org/gems/moesif_rack\n[link-license]: https://raw.githubusercontent.com/Moesif/moesif-rack/master/LICENSE\n[link-source]: https://github.com/moesif/moesif-rack\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoesif%2Fmoesif-rack","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmoesif%2Fmoesif-rack","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoesif%2Fmoesif-rack/lists"}