The filter-logger package

[Tags:library, mit, program, test]

Composable filters to transform objects and control when they are written to server logs.


[Skip to Readme]

Properties

Versions 0.1.0.0, 0.2.0.0, 0.3.0.0, 0.4.0.0, 0.5.0.0, 0.6.0.0
Dependencies aeson, aeson-pretty, ansi-terminal, base (>=4.6 && <5), bytestring, data-default, fast-logger, filter-logger, http-types, scotty, semigroups, time, wai, wai-extra, wai-logger [details]
License MIT
Copyright Copyright: (c) 2017 Joe Canero
Author Joe Canero
Maintainer jmc41493@gmail.com
Category Web
Home page https://github.com/caneroj1/filter-logger#readme
Source repository head: git clone https://github.com/caneroj1/filter-logger
Uploaded Sat Jul 15 23:18:13 UTC 2017 by jmc41493
Distributions NixOS:0.6.0.0, Stackage:0.6.0.0
Downloads 160 total (160 in the last 30 days)
Votes
0 []
Status Docs available [build log]
Last success reported on 2017-07-15 [all 1 reports]
Hackage Matrix CI

Modules

[Index]

Downloads

Maintainer's Corner

For package maintainers and hackage trustees

Readme for filter-logger

Readme for filter-logger-0.6.0.0

filter-logger

Hackage Build Status

Filterable request logging as a wai middleware. Change what data is logged and when.

Usage

Here 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.

Password Filtering


{-# LANGUAGE DeriveGeneric     #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards   #-}

module Main where

import           Data.Aeson
import           GHC.Generics
import           Network.Wai.Middleware.FilterLogger
import           Web.Scotty

data LoginRequest = LoginRequest {
    username :: String
  , password :: String
  } deriving (Generic)

instance FromJSON LoginRequest where
instance ToJSON LoginRequest where

instance LogShowable LoginRequest where
  logShow = logShowJSON

instance LogFilterable LoginRequest where
  prep = logFilterJSON

instance Loggable LoginRequest where

main :: IO ()
main = scotty 3000 $ do
  middleware filterPasswords
  post "/" $ text "SUCCESS"

filterPasswords =
  mkDefaultFilterLogger hidePasswords
  where hidePasswords r@LoginRequest{..} = Just r {password = "*****"}

Sending a POST request to localhost:3000 with a body like

{
  "username": "test-username",
  "password": "myPassw0rd123"
}

will result in a log message like

11/Jul/2017:21:48:20 -0400
200 - OK
0.03ms
{
    "username": "test-username",
    "password": "*****"
}

Chaining Filters

Here is a rather contrived example showing that you can chain these filters together easily and do all sorts of filtering.


{-# LANGUAGE OverloadedStrings #-}

module Main where

import           Control.Monad
import qualified Data.ByteString                     as BS (elem, length)
import           Data.Char
import           Data.Word
import           Network.Wai.Middleware.FilterLogger
import           Web.Scotty

main :: IO ()
main = scotty 3000 $ do
  middleware filteringMiddleware
  post "/" $ text "SUCCESS"

filteringMiddleware =
  mkDefaultFilterLogger (keepShortBodies >=> containing 'c')
  where keepShortBodies bs
          | BS.length bs < 10 = Just bs
          | otherwise         = Nothing
        containing c bs
          | BS.elem (fromIntegral $ ord c) bs = Just bs
          | otherwise                         = Nothing

Sending a POST request to localhost:3000 with a body like

abcdefghi

will result in a log message like

11/Jul/2017:22:00:59 -0400
200 - OK
0.03ms
abcdefghi

If you send a POST request with a body like

abcdefghij

or

abdefghij

you won't see anything in the server logs.

Customization

Customizing the log filtering middleware can be done with the FilterOptions type. It supports two options currently:

  • Detailed logging: Includes the request duration in milliseconds and the response body size. True by default.
  • 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.