{"id":13879023,"url":"https://github.com/renuo/rails_api_logger","last_synced_at":"2025-04-04T08:05:09.952Z","repository":{"id":43476968,"uuid":"341165409","full_name":"renuo/rails_api_logger","owner":"renuo","description":"An Inbound and Outbound requests logger for your Rails application","archived":false,"fork":false,"pushed_at":"2025-02-16T10:13:22.000Z","size":83,"stargazers_count":63,"open_issues_count":0,"forks_count":12,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-03-28T07:04:35.353Z","etag":null,"topics":["api","logging","rails"],"latest_commit_sha":null,"homepage":"https://github.com/renuo/rails_api_logger","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/renuo.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","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,"publiccode":null,"codemeta":null}},"created_at":"2021-02-22T10:42:06.000Z","updated_at":"2025-03-06T13:44:58.000Z","dependencies_parsed_at":"2023-12-15T21:44:28.366Z","dependency_job_id":"ba2cb0ba-66fa-42b5-80ea-0838dd99015c","html_url":"https://github.com/renuo/rails_api_logger","commit_stats":{"total_commits":45,"total_committers":5,"mean_commits":9.0,"dds":0.6,"last_synced_commit":"c71de16632d9e58b8f7622705df2746ed7815466"},"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/renuo%2Frails_api_logger","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/renuo%2Frails_api_logger/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/renuo%2Frails_api_logger/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/renuo%2Frails_api_logger/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/renuo","download_url":"https://codeload.github.com/renuo/rails_api_logger/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247141903,"owners_count":20890651,"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":["api","logging","rails"],"created_at":"2024-08-06T08:02:07.194Z","updated_at":"2025-04-04T08:05:09.928Z","avatar_url":"https://github.com/renuo.png","language":"Ruby","funding_links":[],"categories":["Ruby"],"sub_categories":[],"readme":"# Rails API Logger\n\nThe simplest way to log API requests in your database.\n\nThe Rails API logger gem introduces a set of tools to log and debug API requests.\n\nIt works on two sides:\n\n* **Inbound requests**: API exposed by your application\n* **Outbound requests**: API invoked by your application\n\nThis gem has been extracted from various [Renuo](https://www.renuo.ch) projects.\n\nThis gem creates two database tables to log the following information:\n\n* **path** the path/url invoked\n* **method** the method used to invoke the API (get, post, put, etc...)\n* **request_body** what was included in the request body\n* **response_body** what was included in the response body\n* **response_code** the HTTP response code of the request\n* **started_at** when the request started\n* **ended_at** when the request finished\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'rails_api_logger'\n```\n\nAnd then execute:\n\n```bash\nbundle install\nbin/rails g rails_api_logger:install\nbin/rails db:migrate\n```\n\nThis will generate two tables `inbound_request_logs` and `outbound_request_logs`.\nThese tables will contain the logs.\n\n## Ensure logging of data\n\nRailsApiLogger can use a separate database, to ensure that the logs are written in the database even if a\nsurrounding database transaction is rolled back.\n\nMake sure to add the following in your `config/environments/production.rb`:\n\n```ruby\nconfig.rails_api_logger.connects_to = { database: { writing: :api_logger } }\n```\n\nand [configure a new database](spec/dummy/config/database.yml) accordingly.\n\n\u003e ⚠️ If you skip this step, rails_api_logger will use your primary database but a rollback will also rollback the\n\u003e writing of logs\n\u003e If you are not on SQLite you can point also `api_logger` to the same database! By doing so you can use a single\n\u003e database but still guarantee the writing of logs in an isolated transaction:\n\u003e ```\n\u003e config.rails_api_logger.connects_to = { database: { writing: :primary } }\n\u003e ```\n\n## Log Outbound Requests\n\nGiven an outbound request in the following format:\n\n```ruby\nuri = URI('http://example.com/some_path?query=string')\nhttp = Net::HTTP.start(uri.host, uri.port)\nrequest = Net::HTTP::Get.new(uri)\nresponse = http.request(request)\n```\n\nyou can log it by doing the following:\n\n```ruby\nuri = URI('http://example.com/some_path?query=string')\nhttp = Net::HTTP.start(uri.host, uri.port)\nrequest = Net::HTTP::Get.new(uri)\n\nlog = RailsApiLogger::OutboundRequestLog.from_request(request)\n\nresponse = http.request(request)\n\nlog.response_body = response.body\nlog.response_code = response.code\nlog.save!\n```\n\nYou can also use the provided logger class to do that in a simpler and safer manner:\n\n```ruby\nuri = URI('https://example.com/some_path')\nrequest = Net::HTTP::Post.new(uri)\nrequest.body = { answer: 42 }.to_json\nrequest.content_type = 'application/json'\n\nresponse = RailsApiLogger::Logger.new.call(nil, request) do\n  Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(request) }\nend\n``` \n\nThis will guarantee that the log is always persisted, even in case of errors.\n\n### Database Transactions Caveats\n\nIf you log your outbound requests inside of parent app transactions, your logs will not be persisted if\nthe transaction is rolled-back. Use a separate database to prevent this.\n\n## Log Inbound Requests\n\nIf you are exposing some API you might be interested in logging the requests you receive.\nYou can do so by adding this middleware in `config/application.rb`\n\n```ruby\nconfig.middleware.insert_before Rails::Rack::Logger, RailsApiLogger::Middleware\n``` \n\nthis will by default only log requests that have an impact in your system (POST, PUT, and PATCH calls).\nIf you want to log all requests (also GET ones) use\n\n```ruby\nconfig.middleware.insert_before Rails::Rack::Logger, RailsApiLogger::Middleware, only_state_change: false\n```\n\nIf you want to log only requests on a certain path, you can pass a regular expression:\n\n```ruby\nconfig.middleware.insert_before Rails::Rack::Logger, RailsApiLogger::Middleware, path_regexp: /api/\n```\n\nIf you want to log only requests on a certain host, you can also use a regular expression:\n\n```ruby\nconfig.middleware.insert_before Rails::Rack::Logger, RailsApiLogger::Middleware, host_regexp: /api.example.com/\n```\n\nIf you want to skip logging the response or request body of certain requests, you can pass a regular expression:\n\n```ruby\nconfig.middleware.insert_before Rails::Rack::Logger, RailsApiLogger::Middleware,\n                                skip_request_body_regexp: /api\\/books/,\n                                skip_response_body_regexp: /api\\/letters/\n```\n\nIn the implementation of your API, you can call any time `attach_inbound_request_loggable(model)`\nto attach an already persisted model to the log record.\n\nFor example:\n\n```ruby\n\ndef create\n  @user = User.new(user_params)\n  if @user.save\n    attach_inbound_request_loggable(@user)\n    render json: { id: @user.id }, status: :created\n  else\n    render json: @user.errors.details, status: :unprocessable_entity\n  end\nend\n```\n\nin the User model you can define:\n\n```ruby\nhas_many_inbound_request_logs\n```\n\nto be able to access the inbound logs attached to the model.\n\nYou also have `has_many_outbound_request_logs` and `has_many_request_logs` that includes both.\n\n## RailsAdmin integration\n\nWe provide here some code samples to integrate the models in [RailsAdmin](https://github.com/sferik/rails_admin).\n\nThis configuration will give you some nice views, and searches to work with the logs efficiently.\n\n```ruby\n%w[RailsApiLogger::InboundRequestLog RailsApiLogger::OutboundRequestLog].each do |logging_model|\n  config.model logging_model do\n    list do\n      filters %i[method path response_code request_body response_body created_at]\n      scopes [nil, :failed]\n\n      include_fields :method, :path, :response_code, :created_at\n\n      field :request_body, :string do\n        visible false\n        searchable true\n        filterable true\n      end\n\n      field :response_body, :string do\n        visible false\n        searchable true\n        filterable true\n      end\n    end\n\n    show do\n      include_fields :loggable, :method, :path, :response_code\n      field(:created_at)\n      field(:request_body) do\n        formatted_value { \"\u003cpre\u003e#{JSON.pretty_generate(bindings[:object].request_body)}\u003c/pre\u003e\".html_safe }\n      end\n      field(:response_body) do\n        formatted_value { \"\u003cpre\u003e#{JSON.pretty_generate(bindings[:object].response_body)}\u003c/pre\u003e\".html_safe }\n      end\n    end\n  end\nend\n```\n\n## Development\n\nWe use Appraisals to un on different Rails versions. This is a run example:\n\n```bash\nexport SAME_TARGET=false \nexport SAME_DB=false \nexport TARGET_DB=postgres \nexport BUNDLE_GEMFILE=/Users/alessandrorodi/RenuoWorkspace/rails_api_logger/gemfiles/rails_6.1.gemfile \nbundle exec rails db:create db:migrate\nbundle exec rspec\n```\n\nThese are the possible ENV variables:\n\n* `SAME_TARGET` if true, the api_logger database is the same as the primary one. It will still use two separate\n  connection pools, but they'll point to the same database. This cannot be set to true if TARGET_DB is sqlite because\n  sqlite does not support multiple connection pools to the same database.\n* `SAME_DB` if true, the api_logger uses the primary database. In this case SAME_TARGET is ignored.\n* `TARGET_DB` the database to use. Can be `postgres`, `mysql`, or `sqlite`.\n* `BUNDLE_GEMFILE` the gemfile to use. This is used to run the tests on different Rails versions.\n\nPossible combinations:\n\n| SAME_DB | SAME_TARGET | TARGET_DB | Description                                                          |\n|---------|-------------|-----------|----------------------------------------------------------------------|\n| false   | false       | postgres  | Separate database, separate connection pool.                         |\n| false   | true        | postgres  | Same database, separate connection pool.                             |\n| true    | -           | postgres  | Same connection pool so the separate target is ignored.              |\n| false   | false       | sqlite    | Separate database, separate connection pool.                         |\n| false   | true        | sqlite    | Not allowed. sqlite cannot have two connection pools to the same db. |\n| true    | -           | sqlite    | Same connection pool so the separate target is ignored.              |\n\n\nTo install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the\nversion number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version,\npush 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/renuo/rails_api_logger.\nThis project is intended to be a safe, welcoming space for collaboration.\n\nTry to be a decent human being while interacting with other people.\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frenuo%2Frails_api_logger","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frenuo%2Frails_api_logger","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frenuo%2Frails_api_logger/lists"}