iT邦幫忙

2025 iThome 鐵人賽

DAY 25
0

這篇來介紹的是在 Effect 裡面怎麼寫 log ,不知道各位平常有沒有習慣在寫 log ,如果程式有 log 的話,可以幫助我們了解程式現在的狀態,在除錯上會很有幫助。如果有在寫 log 可能會知道像是 pino 或是像 winston 這樣的 logging 套件,那 Effect 的 logging 又跟這些既有的套件有什麼差別呢?我們來看下去

如何使用 Effect 的 logging

Effect 已經內建了 log 的機制,你只需要呼叫 Effect.log 或是同系列的 function ,就會可以紀錄 log 了

pipe(
  Effect.gen(function*() {
    yield* Effect.log("log")
    yield* Effect.logInfo("logInfo")
    // 還記得之前提過 Cause 這個 Effect 用來完整表達錯誤類型的型態嗎?
    // 如果這邊直接傳入 Error 反而不會正常顯示
    yield* Effect.logError("logError", Cause.fail(new Error("oh no")))
  }),
  Effect.runPromise
)

(playground link)

而以上的程式會顯示

timestamp=2025-10-07T11:46:57.679Z level=INFO fiber=#0 message=log
timestamp=2025-10-07T11:46:57.680Z level=INFO fiber=#0 message=logInfo
timestamp=2025-10-07T11:46:57.680Z level=ERROR fiber=#0 message=logError cause="Error: oh no
    at eval (/home/r24e23sdiw9w1oqo1ljpo851jbidnw-h5th/playground/dist/main.js:7:69)
    at eval (/home/r24e23sdiw9w1oqo1ljpo851jbidnw-h5th/playground/node_modules/.pnpm/effect@3.17.14/node_modules/effect/dist/cjs/internal/fiberRuntime.js:129:77)"

log 資料

在 pino 裡有個很方便的功能是你可以把一個 object 傳入第一個參數,例如

pino.info({ request }, 'receieve request')

這樣你就會在 log 中看到 request 的詳細內容,在 Effect 中要達成類似的效果,需要使用 Effect.annotateLogs

pipe(
  Effect.gen(function*() {
    yield* Effect.log("log")
  }),
  // 這樣上面的 Effect 中的所有 log ,包含 Effect 中的 Effect 中的 log 都會有同樣的資料
  Effect.annotateLogs({
    foo: "bar"
  }),
  Effect.runPromise
)

(playground link)

上面的輸出是:

timestamp=2025-10-07T12:05:36.292Z level=INFO fiber=#0 message=log foo=bar

使用 span 計時

我們一個 Effect 代表著一個任務,如果我們想要測量一下完成一個任務花了多少時間,我們不用再自己計算 Date.now() - start 了,我們只需要 Effect.withLogSpan

pipe(
  Effect.gen(function*() {
    yield* Effect.log('first')

    yield* Effect.sleep('500 millis')

    yield* Effect.log('second')

    yield* Effect.sleep('500 millis')  

    yield* Effect.log('done')
  }),
  // 你可以幫你計時的區塊取個名字,這代表你可以計時多個區塊
  Effect.withLogSpan('span'),
  Effect.runPromise
)

(playground link)

上面在每次 log 的同時就會輸出時間了

timestamp=2025-10-07T12:20:32.207Z level=INFO fiber=#0 message=first span=0ms
timestamp=2025-10-07T12:20:32.718Z level=INFO fiber=#0 message=second span=511ms
timestamp=2025-10-07T12:20:33.225Z level=INFO fiber=#0 message=done span=1018ms

Effect logging vs pino or winstion

以上簡單的介紹了一個使用方法還有 Effect logging 的特點。而 Effect logging 跟 pino 還有 winstion 這些套件比起來, Effect 有著以下的優勢:

  • 跟流程管理整合,可以知道任務何時開始與結束
  • 可以很容易的修改一個範圍內的 logging level 或是要 log 的資料

但缺點其實也挺明顯的

  • 完全不能在 Effect 外使用,如果你在 Effect 中有部份的程式未使用 Effect 那就沒辦法記 log
  • error 需要包成 Cause 才會正常顯示

這篇主要是介紹基本的 logging 的使用, Effect 很大的善用了自己主要的流程管理功能來增強 logging ,比如計時跟 annotate 資料在所有的 log 上,不過在 log error 上就稍微不便。如果你的程式已經在用 Effect 了,整體而言還是很推薦使用內建的 logging,特別是下一篇要來看 Effect 的 observability 的整合,絕對是值得使用的

Reference


上一篇
23. Effect 應用 2 :用 orpc 與 Effect 打造強韌的 API 介面
系列文
Effect 魔法:打造堅不可摧的應用程式25
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言