You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于aws-lambda-haskell-runtime与Amazonka的性能问题:如何获取每个查询的耗时?

解决Amazonka中获取API调用耗时的问题

我之前在使用Amazonka结合Lambda Haskell Runtime时也遇到过类似的性能排查需求,确实默认的Trace日志不会输出每个API调用的耗时。这里有几个可行的方案供你参考:

1. 手动包装send调用(推荐用于API操作级别的耗时统计)

这是最直接且可控的方式,因为Amazonka的所有API请求最终都会通过send函数执行。我们可以写一个包装函数,在调用前后记录时间并计算差值:

import Data.Time.Clock
import Network.AWS (AWS, send, Env)
import Control.Monad.Reader (runReaderT)

-- 包装send函数,返回结果和耗时
timedSend :: Env -> AWS a -> IO (a, NominalDiffTime)
timedSend env req = do
    startTime <- getCurrentTime
    result <- runReaderT (send req) env
    endTime <- getCurrentTime
    let duration = diffUTCTime endTime startTime
    -- 这里可以替换成你需要的日志输出逻辑,比如写入CloudWatch或者Lambda日志
    putStrLn $ "[AWS API] Call took " ++ show duration
    return (result, duration)

-- 使用示例
main = do
    env <- newEnv Discover
    (_, duration) <- timedSend env (listBuckets :: AWS ListBucketsResponse)
    putStrLn $ "List buckets operation took: " ++ show duration

这个方案的优势是:

  • 统计的是整个Amazonka API操作的总耗时,包括重试、分页等内部逻辑
  • 完全自定义输出格式和处理逻辑,比如可以把耗时上报到监控系统
  • 不需要依赖额外库,代码侵入性低

2. 利用http-client中间件(用于底层HTTP请求级别的耗时统计)

Amazonka底层基于http-client实现,所以我们可以通过自定义http-client的ManagerSettings添加中间件,拦截所有HTTP请求并记录耗时:

import Network.HTTP.Client
import Network.AWS (newEnv, envManager, Env(..))
import Data.Time.Clock
import Data.IORef

-- 创建一个带耗时统计的中间件
timingMiddleware :: ManagerSettings -> ManagerSettings
timingMiddleware baseSettings = baseSettings
    { managerModifyRequest = \req -> do
        -- 在请求发起前记录时间,存在IORef里
        startTimeRef <- newIORef =<< getCurrentTime
        let req' = req { requestUserState = Just startTimeRef }
        managerModifyRequest baseSettings req'
    , managerResponseHook = \req resp -> do
        -- 在响应返回后读取开始时间,计算耗时
        case requestUserState req of
            Just startTimeRef -> do
                startTime <- readIORef startTimeRef
                endTime <- getCurrentTime
                let duration = diffUTCTime endTime startTime
                    uri = show $ getUri req
                putStrLn $ "[HTTP Request] " ++ uri ++ " took " ++ show duration
            Nothing -> return ()
        -- 执行原有的响应钩子
        managerResponseHook baseSettings req resp
    }

-- 创建带计时中间件的AWS环境
createTimedEnv :: IO Env
createTimedEnv = do
    baseEnv <- newEnv Discover
    let baseManagerSettings = managerSettings $ envManager baseEnv
        timedManagerSettings = timingMiddleware baseManagerSettings
    timedManager <- newManager timedManagerSettings
    return baseEnv { envManager = timedManager }

这个方案的特点是:

  • 统计的是每个底层HTTP请求的耗时,如果Amazonka的API操作包含多次HTTP请求(比如分页、重试),会分别记录
  • 全局生效,不需要修改每个send调用
  • 适合排查网络层面的性能问题,比如单个请求的延迟

3. 关于runAWST的补充

runAWST本身并没有提供直接的钩子来记录每个API调用的耗时,不过你可以在runAWST的上下文中使用上面的包装函数,或者传入带计时中间件的Env,就能实现耗时统计的需求。


内容的提问来源于stack exchange,提问作者GlinesMome

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 03:38:13