Add error log level

This commit is contained in:
steve-chavez
2020-10-06 14:21:46 -05:00
committed by Steve Chavez
parent e9efcc70a5
commit f6b6abe734
4 changed files with 63 additions and 22 deletions
+2
View File
@@ -59,6 +59,7 @@ library
, contravariant-extras >= 0.3.3 && < 0.4 , contravariant-extras >= 0.3.3 && < 0.4
, cookie >= 0.4.2 && < 0.5 , cookie >= 0.4.2 && < 0.5
, either >= 4.4.1 && < 5.1 , either >= 4.4.1 && < 5.1
, fast-logger >= 2.4.5
, gitrev >= 1.2 && < 1.4 , gitrev >= 1.2 && < 1.4
, hasql >= 1.4 && < 1.5 , hasql >= 1.4 && < 1.5
, hasql-pool >= 0.5 && < 0.6 , hasql-pool >= 0.5 && < 0.6
@@ -84,6 +85,7 @@ library
, wai >= 3.2.1 && < 3.3 , wai >= 3.2.1 && < 3.3
, wai-cors >= 0.2.5 && < 0.3 , wai-cors >= 0.2.5 && < 0.3
, wai-extra >= 3.0.19 && < 3.2 , wai-extra >= 3.0.19 && < 3.2
, wai-logger >= 2.3.2
, wai-middleware-static >= 0.8.1 && < 0.10 , wai-middleware-static >= 0.8.1 && < 0.10
default-language: Haskell2010 default-language: Haskell2010
default-extensions: OverloadedStrings default-extensions: OverloadedStrings
+6 -5
View File
@@ -266,11 +266,12 @@ readAppConfig cfgPath = do
parseLogLevel :: C.Key -> C.Parser C.Config LogLevel parseLogLevel :: C.Key -> C.Parser C.Config LogLevel
parseLogLevel k = parseLogLevel k =
C.optional k C.string >>= \case C.optional k C.string >>= \case
Nothing -> pure LogInfo Nothing -> pure LogInfo
Just "" -> pure LogInfo Just "" -> pure LogInfo
Just "crit" -> pure LogCrit Just "crit" -> pure LogCrit
Just "info" -> pure LogInfo Just "error" -> pure LogError
Just _ -> fail "Invalid logging level. Check your configuration." Just "info" -> pure LogInfo
Just _ -> fail "Invalid logging level. Check your configuration."
reqString :: C.Key -> C.Parser C.Config Text reqString :: C.Key -> C.Parser C.Config Text
reqString k = C.required k C.string reqString k = C.required k C.string
+54 -16
View File
@@ -8,23 +8,26 @@ Description : Sets CORS policy. Also the PostgreSQL GUCs, role, search_path and
module PostgREST.Middleware where module PostgREST.Middleware where
import qualified Data.Aeson as JSON import qualified Data.Aeson as JSON
import qualified Data.ByteString.Char8 as BS import qualified Data.ByteString.Char8 as BS
import qualified Data.CaseInsensitive as CI import qualified Data.CaseInsensitive as CI
import Data.Function (id) import Data.Function (id)
import qualified Data.HashMap.Strict as M import qualified Data.HashMap.Strict as M
import Data.List (lookup) import Data.List (lookup)
import Data.Scientific (FPFormat (..), import Data.Scientific (FPFormat (..),
formatScientific, isInteger) formatScientific,
import Data.Text (strip) isInteger)
import qualified Hasql.Transaction as H import qualified Data.Text as T
import qualified Hasql.Transaction as H
import Network.HTTP.Types.Status (statusCode)
import Network.Wai.Logger (showSockAddr)
import System.Log.FastLogger (toLogStr)
import Network.Wai (Application, Request, import Network.Wai
Response, requestHeaders)
import Network.Wai.Middleware.Cors (CorsResourcePolicy (..), import Network.Wai.Middleware.Cors (CorsResourcePolicy (..),
cors) cors)
import Network.Wai.Middleware.Gzip (def, gzip) import Network.Wai.Middleware.Gzip (def, gzip)
import Network.Wai.Middleware.RequestLogger (logStdout) import Network.Wai.Middleware.RequestLogger
import Network.Wai.Middleware.Static (only, staticPolicy) import Network.Wai.Middleware.Static (only, staticPolicy)
import PostgREST.ApiRequest (ApiRequest (..)) import PostgREST.ApiRequest (ApiRequest (..))
@@ -33,6 +36,7 @@ import PostgREST.QueryBuilder (setLocalQuery, setLocalSearchPathQuery)
import PostgREST.Types (LogLevel (..)) import PostgREST.Types (LogLevel (..))
import Protolude hiding (head, toS) import Protolude hiding (head, toS)
import Protolude.Conv (toS) import Protolude.Conv (toS)
import System.IO.Unsafe (unsafePerformIO)
-- | Runs local(transaction scoped) GUCs for every request, plus the pre-request function -- | Runs local(transaction scoped) GUCs for every request, plus the pre-request function
runPgLocals :: AppConfig -> M.HashMap Text JSON.Value -> runPgLocals :: AppConfig -> M.HashMap Text JSON.Value ->
@@ -57,12 +61,46 @@ runPgLocals conf claims app req = do
anon = JSON.String . toS $ configAnonRole conf anon = JSON.String . toS $ configAnonRole conf
preReq = (\f -> "select " <> toS f <> "();") <$> configPreReq conf preReq = (\f -> "select " <> toS f <> "();") <$> configPreReq conf
-- | Log in apache format. Only requests with a failure status.
-- | There's no easy way to filter logs in the apache format on https://hackage.haskell.org/package/wai-extra-3.0.29.2/docs/Network-Wai-Middleware-RequestLogger.html#t:OutputFormat.
-- | So here we copy https://github.com/kazu-yamamoto/logger/blob/a4f51b909a099c51af7a3f75cf16e19a06f9e257/wai-logger/Network/Wai/Logger/Apache.hs#L45
-- | TODO: Add the ability to filter apache logs on wai-extra and remove this function.
pgrstFormat :: OutputFormatter
pgrstFormat date req status responseSize =
if statusCode status < 400
then toLogStr BS.empty
else toLogStr (getSourceFromSocket req)
<> " - - ["
<> toLogStr date
<> "] \""
<> toLogStr (requestMethod req)
<> " "
<> toLogStr (rawPathInfo req <> rawQueryString req)
<> " "
<> toLogStr (show (httpVersion req)::Text)
<> "\" "
<> toLogStr (show (statusCode status)::Text)
<> " "
<> toLogStr (maybe "-" show responseSize::Text)
<> " \""
<> toLogStr (fromMaybe mempty $ requestHeaderReferer req)
<> "\" \""
<> toLogStr (fromMaybe mempty $ requestHeaderUserAgent req)
<> "\"\n"
where
getSourceFromSocket = BS.pack . showSockAddr . remoteHost
pgrstMiddleware :: LogLevel -> Application -> Application pgrstMiddleware :: LogLevel -> Application -> Application
pgrstMiddleware logLev = pgrstMiddleware logLevel =
(if logLev == LogCrit then id else logStdout) logger
. gzip def . gzip def
. cors corsPolicy . cors corsPolicy
. staticPolicy (only [("favicon.ico", "static/favicon.ico")]) . staticPolicy (only [("favicon.ico", "static/favicon.ico")])
where
logger = case logLevel of
LogCrit -> id
LogError -> unsafePerformIO $ mkRequestLogger def { outputFormat = CustomOutputFormat pgrstFormat }
LogInfo -> logStdout
defaultCorsPolicy :: CorsResourcePolicy defaultCorsPolicy :: CorsResourcePolicy
defaultCorsPolicy = CorsResourcePolicy Nothing defaultCorsPolicy = CorsResourcePolicy Nothing
@@ -84,7 +122,7 @@ corsPolicy req = case lookup "origin" headers of
where where
headers = requestHeaders req headers = requestHeaders req
accHeaders = case lookup "access-control-request-headers" headers of accHeaders = case lookup "access-control-request-headers" headers of
Just hdrs -> map (CI.mk . toS . strip . toS) $ BS.split ',' hdrs Just hdrs -> map (CI.mk . toS . T.strip . toS) $ BS.split ',' hdrs
Nothing -> [] Nothing -> []
unquoted :: JSON.Value -> Text unquoted :: JSON.Value -> Text
+1 -1
View File
@@ -539,4 +539,4 @@ data ConnectionStatus
| FatalConnectionError Text | FatalConnectionError Text
deriving (Eq, Show) deriving (Eq, Show)
data LogLevel = LogCrit | LogInfo deriving (Eq, Show) data LogLevel = LogCrit | LogError | LogInfo deriving (Eq, Show)