{"id":15288105,"url":"https://github.com/caneroj1/filter-logger","last_synced_at":"2026-03-16T20:01:37.758Z","repository":{"id":62435983,"uuid":"96946615","full_name":"caneroj1/filter-logger","owner":"caneroj1","description":"Filterable request logging as wai middleware","archived":false,"fork":false,"pushed_at":"2017-07-16T15:47:39.000Z","size":38,"stargazers_count":7,"open_issues_count":1,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-04-25T05:42:36.625Z","etag":null,"topics":["haskell","http","logging"],"latest_commit_sha":null,"homepage":null,"language":"Haskell","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/caneroj1.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}},"created_at":"2017-07-11T23:52:53.000Z","updated_at":"2023-03-05T01:09:44.000Z","dependencies_parsed_at":"2022-11-01T21:16:48.775Z","dependency_job_id":null,"html_url":"https://github.com/caneroj1/filter-logger","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/caneroj1%2Ffilter-logger","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/caneroj1%2Ffilter-logger/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/caneroj1%2Ffilter-logger/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/caneroj1%2Ffilter-logger/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/caneroj1","download_url":"https://codeload.github.com/caneroj1/filter-logger/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248674644,"owners_count":21143760,"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":["haskell","http","logging"],"created_at":"2024-09-30T15:44:08.942Z","updated_at":"2026-03-16T20:01:37.679Z","avatar_url":"https://github.com/caneroj1.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# filter-logger\n[Hackage](https://hackage.haskell.org/package/filter-logger#readme)\n[![Build Status](https://travis-ci.org/caneroj1/filter-logger.svg?branch=master)](https://travis-ci.org/caneroj1/filter-logger)\n\nFilterable request logging as a wai middleware. Change what data is logged and when.\n\n## Usage\n\nHere is one example from the **examples/password** directory where we use the filter logger to implement password filtering. The example uses `scotty` for our web server, and we use the `logShowJSON` and `logFilterJSON` helper functions to help us create our instances.\n\n### Password Filtering\n\n```haskell\n\n{-# LANGUAGE DeriveGeneric     #-}\n{-# LANGUAGE OverloadedStrings #-}\n{-# LANGUAGE RecordWildCards   #-}\n\nmodule Main where\n\nimport           Data.Aeson\nimport           GHC.Generics\nimport           Network.Wai.Middleware.FilterLogger\nimport           Web.Scotty\n\ndata LoginRequest = LoginRequest {\n    username :: String\n  , password :: String\n  } deriving (Generic)\n\ninstance FromJSON LoginRequest where\ninstance ToJSON LoginRequest where\n\ninstance LogShowable LoginRequest where\n  logShow = logShowJSON\n\ninstance LogFilterable LoginRequest where\n  prep = logFilterJSON\n\ninstance Loggable LoginRequest where\n\nmain :: IO ()\nmain = scotty 3000 $ do\n  middleware filterPasswords\n  post \"/\" $ text \"SUCCESS\"\n\nfilterPasswords =\n  mkDefaultFilterLogger hidePasswords\n  where hidePasswords r@LoginRequest{..} = Just r {password = \"*****\"}\n\n```\n\nSending a POST request to localhost:3000 with a body like\n```\n{\n  \"username\": \"test-username\",\n  \"password\": \"myPassw0rd123\"\n}\n```\n\n  will result in a log message like\n```\n11/Jul/2017:21:48:20 -0400\n200 - OK\n0.03ms\n{\n    \"username\": \"test-username\",\n    \"password\": \"*****\"\n}\n```\n\n### Chaining Filters\n\nHere is a rather contrived example showing that you can chain these filters together easily and do all sorts of filtering.\n\n```haskell\n\n{-# LANGUAGE OverloadedStrings #-}\n\nmodule Main where\n\nimport           Control.Monad\nimport qualified Data.ByteString                     as BS (elem, length)\nimport           Data.Char\nimport           Data.Word\nimport           Network.Wai.Middleware.FilterLogger\nimport           Web.Scotty\n\nmain :: IO ()\nmain = scotty 3000 $ do\n  middleware filteringMiddleware\n  post \"/\" $ text \"SUCCESS\"\n\nfilteringMiddleware =\n  mkDefaultFilterLogger (keepShortBodies \u003e=\u003e containing 'c')\n  where keepShortBodies bs\n          | BS.length bs \u003c 10 = Just bs\n          | otherwise         = Nothing\n        containing c bs\n          | BS.elem (fromIntegral $ ord c) bs = Just bs\n          | otherwise                         = Nothing\n\n```\n\nSending a POST request to localhost:3000 with a body like\n```\nabcdefghi\n```\n\nwill result in a log message like\n```\n11/Jul/2017:22:00:59 -0400\n200 - OK\n0.03ms\nabcdefghi\n```\n\nIf you send a POST request with a body like\n```\nabcdefghij\n```\nor\n```\nabdefghij\n```\n\nyou won't see anything in the server logs.\n\n## Customization\n\nCustomizing the log filtering middleware can be done with the `FilterOptions` type. It supports two options currently:\n* Detailed logging: Includes the request duration in milliseconds and the response body size. `True` by default.\n* Log when the request body is empty: Boolean value indicating whether or not to create log messages when there is no request body. `True` by default.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcaneroj1%2Ffilter-logger","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcaneroj1%2Ffilter-logger","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcaneroj1%2Ffilter-logger/lists"}