1

私は Haskell のバックエンド アプリケーションに Scotty を使用しており、すべてのリクエストをファイルに記録することに関心があります。既存の wai-middleware requestloggerは、 FileLogSpec が許可する複数の短いログファイルが好きなので、 FileLogSpecのプロパティが欲しいので十分ではありません。

ログの問題については別の解決策も受け入れていますが、Scotty からの切り替えには興味がありません。

私の問題は、最初のリクエストの後に次のエラーが発生することです。

openFile: resource busy (file is locked)
openFile: resource busy (file is locked)

アプリケーションはログを完全に停止します。

wai-logger をミドルウェアにする現在の実装は次のとおりです。

-- type Middleware = Application -> Application
-- Type Application = Request -> (Response -> IO ResponseReceived) -> IO ResponseReceived
mw :: Wai.Middleware
mw (app::Wai.Application) (req::Request) (fRes::(Response -> IO ResponseReceived)) =
    app req myResponseFunction
    where
        myResponseFunction :: Response -> IO ResponseReceived
        myResponseFunction response = do
            logger' <- logger
            logger' req (Wai.responseStatus response) Nothing
            fRes response
        logger :: IO Logger.ApacheLogger
        logger = createLoggerActions >>= return . Logger.apacheLogger
        createLoggerActions :: IO Logger.ApacheLoggerActions
        createLoggerActions = let
            -- 5 MB in bytes = 5242880
            mb5InBytes = 5242880
            -- From fast-logger default
            defaultBufSize = 4096 in
                Logger.initLogger
                Logger.FromFallback
                (Logger.LogFile Logger.FileLogSpec {Logger.log_file = "reqLogger", Logger.log_file_size = mb5InBytes, Logger.log_backup_number = 5} defaultBufSize)
                ( return $ B.pack "%d/%b/%Y:%T %z")

次のように、ブラケットを使用してロガーをクリーンアップしようとしました。

mw :: Wai.Middleware    
mw (app::Wai.Application) (req::Request) (fRes::(Response -> IO ResponseReceived)) =
    let loggerActions = createLoggerActions in
        bracket_ setup (teardown loggerActions) $ 
        app req (myResponseFunction loggerActions)
    where
        myResponseFunction :: IO Logger.ApacheLoggerActions -> Response -> IO ResponseReceived
        myResponseFunction loggerActions response = do
            logger' <- logger loggerActions
            logger' req (Wai.responseStatus response) Nothing
            fRes response
        logger :: IO Logger.ApacheLoggerActions -> IO Logger.ApacheLogger
        logger loggerActions = loggerActions >>= return . Logger.apacheLogger
        createLoggerActions :: IO Logger.ApacheLoggerActions
        createLoggerActions = let
            -- 5 MB in bytes = 5242880
            mb5InBytes = 5242880
            -- From fast-logger default
            defaultBufSize = 4096 in
                Logger.initLogger
                Logger.FromFallback
                (Logger.LogFile Logger.FileLogSpec {Logger.log_file = "reqLogger", Logger.log_file_size = mb5InBytes, Logger.log_backup_number = 5} defaultBufSize)
                ( return $ B.pack "%d/%b/%Y:%T %z")
        setup :: IO ()
        setup = return ()
        teardown :: IO (Logger.ApacheLoggerActions) -> IO ()
        teardown loggerActions = loggerActions >>= Logger.logRemover

そして、これが私がそれを使用する方法です:

someFunc :: IO ()
someFunc = do
    appConfig <- loadAppConfig
    workingDir <- Dir.getCurrentDirectory
    putStrLn $ "Working directory: " <> workingDir
    case appConfig of
        Nothing -> putStrLn "Failed to load appconfig.json"
        Just appConfig' ->
            let checkSizeRequirement' = checkSizeRequirement (sizeLimitGB appConfig') in
                scotty 3000 $ do
                    --middleware logStdoutDev
                    middleware $ mw
                    middleware $ staticPolicy (addBase "./ElmFeFMI/")
                    post "/api/fmichecker" ...

残念ながら、これは同じ結果につながりました。

wai ロガーにも問題を作成しました: https://github.com/kazu-yamamoto/logger/issues/183

完全なソースはこちらから入手できます: https://github.com/into-cps-association/utilities_backend

4

1 に答える 1