@@ -1366,11 +1366,6 @@ route Api = AuthApi | ClientApi | FederationApi | FederationVerifyApi | Federati
13661366-- Helpers
13671367-- ============================================
13681368
1369−-- Structured log helpers (severity-prefixed for operator filtering)
1370−logInfo = \msg -> println ("[INFO] " ++ msg)
1371−logWarn = \msg -> println ("[WARN] " ++ msg)
1372−logError = \msg -> println ("[ERROR] " ++ msg)
1373−
13741369-- JSON structured log helper for machine-parseable events.
13751370-- Outputs: {"level":"<level>","event":"<event>","msg":"<message>"}
13761371-- Use for key operational events that monitoring pipelines need to parse
@@ -1378,7 +1373,11 @@ logError = \msg -> println ("[ERROR] " ++ msg)
13781373-- Plain-text logInfo/logWarn/logError remain for human-readable context.
13791374-- Values are escaped (quotes and backslashes) to produce valid JSON even
13801375-- when msg contains user-controlled data (e.g., error strings, server names).
1381−logEvent = \level event msg -> println ("{\"level\":\"" ++ escapeJsonString level ++ "\",\"event\":\"" ++ escapeJsonString event ++ "\",\"msg\":\"" ++ escapeJsonString msg ++ "\"}")
1376+logEvent = \level event msg ->
1377+ let formatted = "{\"level\":\"" ++ escapeJsonString level ++ "\",\"event\":\"" ++ escapeJsonString event ++ "\",\"msg\":\"" ++ escapeJsonString msg ++ "\"}"
1378+ in if level == "error" then logError formatted
1379+ else if level == "warn" then logWarn formatted
1380+ else logInfo formatted
13821381
13831382-- Structured key=value logging: formats message as "k1=v1 k2=v2 ..." for consistent
13841383-- machine-parseable log entries. Wraps logEvent with key-value pair formatting.
@@ -8244,7 +8243,7 @@ handleCancelMessage = \messageId to authorization clientIp respond -> do
82448243 -- from all dedup sets (messages, ackedIds, deliveredIds).
82458244 nonceResult <- updateForwardNonce b messageId to t
82468245 yield {cancelled: True {}, cancelServers: allCancelServers, nonceLruEvicted: nonceResult.lruEvicted, nonceOldestAge: nonceResult.oldestRetainedAge}
8247− -- Log nonce eviction outside atomic block (println can't run inside STM)
8246+ -- Log nonce eviction outside atomic block (IO can't run inside STM)
82488247 logNonceEviction (pubkeyBucket to) cancelResult.nonceLruEvicted cancelResult.nonceOldestAge
82498248 -- Notify recipient that this message was retracted (delivered via next poll)
82508249 when cancelResult.cancelled (do
@@ -8334,7 +8333,7 @@ sendBatchInner = \senderKey messages t acc ->
83348333 sendBatchInner senderKey sameR.rest t (union acc results)
83358334
83368335-- Pre-generate message IDs and validate timestamps for a group of messages.
8337−-- IO actions (genToken, logWarn) can't run inside atomic, so this runs outside.
8336+-- IO actions (genToken, logging) can't run inside atomic, so this runs outside.
83388337prepareBatchMessages = \messages t acc ->
83398338 case headOf messages of
83408339 Nothing {} -> yield acc
@@ -9119,11 +9118,11 @@ serve = \req -> do
91199118 -- Polls only logged when slow (> slowRequestThreshold) to avoid log volume from long-poll traffic.
91209119 if path != ""
91219120 then do
9122− println ("{\"level\":\"info\",\"event\":\"access\",\"req\":\"" ++ escapeJsonString reqId ++ "\",\"path\":\"" ++ escapeJsonString path ++ "\",\"ms\":" ++ show latency ++ (if ip != "" then ",\"ip\":\"" ++ escapeJsonString ip ++ "\"" else "") ++ "}")
9121+ logInfo ("{\"event\":\"access\",\"req\":\"" ++ escapeJsonString reqId ++ "\",\"path\":\"" ++ escapeJsonString path ++ "\",\"ms\":" ++ show latency ++ (if ip != "" then ",\"ip\":\"" ++ escapeJsonString ip ++ "\"" else "") ++ "}")
91239122 when (latency > slowRequestThreshold)
91249123 (logEvent "warn" "slow_request" (path ++ " " ++ show latency ++ "ms"))
91259124 else when (latency > slowRequestThreshold) (do
9126− println ("{\"level\":\"warn\",\"event\":\"access\",\"req\":\"" ++ escapeJsonString reqId ++ "\",\"path\":\"poll\",\"ms\":" ++ show latency ++ (if ip != "" then ",\"ip\":\"" ++ escapeJsonString ip ++ "\"" else "") ++ ",\"slow\":true}")
9125+ logWarn ("{\"event\":\"access\",\"req\":\"" ++ escapeJsonString reqId ++ "\",\"path\":\"poll\",\"ms\":" ++ show latency ++ (if ip != "" then ",\"ip\":\"" ++ escapeJsonString ip ++ "\"" else "") ++ ",\"slow\":true}")
91279126 logEvent "warn" "slow_request" ("poll " ++ show latency ++ "ms"))
91289127
91299128-- ============================================