316 Commits

Author SHA1 Message Date
Nanaloveyuki f44a4794ec 🩹 Fix the major version must be 0 2026-06-27 10:51:37 +08:00
Nanaloveyuki 0cbe25a551 🔊 Update 1.0.0 2026-06-27 10:45:36 +08:00
Nanaloveyuki 4cc43def73 ⬆️ Update Async and Mbt Version 2026-06-27 10:44:51 +08:00
Nanaloveyuki 812c4c21a8 💚 Fix CSS Style lost 2026-06-14 16:28:01 +08:00
Nanaloveyuki cdfe0117a0 👷 Update Doc CI for errors 2026-06-14 16:19:13 +08:00
Nanaloveyuki b43dbdecfb 📌 Update moonbit-syntax-highlighter 2026-06-14 15:59:06 +08:00
Nanaloveyuki 0cfb308fa2 Add package-lock 2026-06-14 15:43:01 +08:00
Nanaloveyuki a0e09fb30f Add VitePress docs site with MoonBit highlighting 2026-06-14 15:17:25 +08:00
Nanaloveyuki dfae044f75 🔨 wrap native file ffi symbols locally 2026-06-14 13:03:03 +08:00
Nanaloveyuki 5e80593ae0 clean native rotation test artifacts 2026-06-14 12:57:48 +08:00
Nanaloveyuki 31f06f5724 🐛 fix native file sink lifecycle behavior 2026-06-14 12:55:29 +08:00
Nanaloveyuki 159f534164 📝 clarify global warn default forwarding 2026-06-14 12:21:02 +08:00
Nanaloveyuki ea0d687da0 📝 clarify global error default forwarding 2026-06-14 12:19:49 +08:00
Nanaloveyuki ce87e32837 📝 clarify global info default forwarding 2026-06-14 12:15:42 +08:00
Nanaloveyuki 866e374ac8 📝 clarify global log default forwarding 2026-06-14 12:13:57 +08:00
Nanaloveyuki aaba931db6 📝 clarify sync log override semantics 2026-06-14 12:09:38 +08:00
Nanaloveyuki 04f7742238 📝 clarify default target snapshot semantics 2026-06-14 12:05:28 +08:00
Nanaloveyuki cf23bb6dbe 📝 clarify default level snapshot semantics 2026-06-14 12:03:45 +08:00
Nanaloveyuki bf27dacf23 📝 clarify default logger snapshot semantics 2026-06-14 12:01:54 +08:00
Nanaloveyuki 0a9bcd696b 📝 clarify sync level threshold derivation 2026-06-14 11:59:01 +08:00
Nanaloveyuki 8fb9beb008 📝 clarify sync timestamp derivation 2026-06-14 11:55:55 +08:00
Nanaloveyuki 5514009abe 📝 clarify sync patch wrapper contract 2026-06-14 11:54:18 +08:00
Nanaloveyuki c17883262a 📝 clarify sync filter wrapper contract 2026-06-14 11:52:32 +08:00
Nanaloveyuki 5476a64478 📝 clarify queued logger wrapper contract 2026-06-14 11:49:15 +08:00
Nanaloveyuki 685797783c 📝 clarify async filter derivation 2026-06-14 11:46:40 +08:00
Nanaloveyuki 11b49208b2 📝 clarify async patch derivation 2026-06-14 11:44:54 +08:00
Nanaloveyuki 18dc8d5860 📝 clarify async level threshold derivation 2026-06-14 11:42:58 +08:00
Nanaloveyuki 18f6bf9eb5 📝 clarify async timestamp derivation 2026-06-14 11:41:24 +08:00
Nanaloveyuki 958a7fd26f 📝 clarify async context field storage 2026-06-14 11:39:38 +08:00
Nanaloveyuki 1124868bd8 📝 clarify logger bind alias contract 2026-06-14 11:37:35 +08:00
Nanaloveyuki c800042e46 📝 clarify async logger child contract 2026-06-14 11:35:29 +08:00
Nanaloveyuki fe7665b9f6 📝 clarify logger child composition contract 2026-06-14 11:33:49 +08:00
Nanaloveyuki 93cadcc7f1 📝 clarify logger context field binding 2026-06-14 11:28:42 +08:00
Nanaloveyuki 480c5ad602 📝 clarify logger target replacement 2026-06-14 11:27:11 +08:00
Nanaloveyuki 5720ba6203 📝 clarify logger trace helper routing 2026-06-14 11:23:34 +08:00
Nanaloveyuki 9630c6cc3b 📝 clarify logger debug helper routing 2026-06-14 11:22:15 +08:00
Nanaloveyuki 6eec61eb2d 📝 clarify async warn helper routing 2026-06-14 11:20:35 +08:00
Nanaloveyuki 3a216a2ada 📝 clarify async error helper routing 2026-06-14 11:19:08 +08:00
Nanaloveyuki b0364fdd51 📝 clarify async info helper routing 2026-06-14 11:17:42 +08:00
Nanaloveyuki 0b2e35d138 📝 clarify logger error helper routing 2026-06-14 11:16:22 +08:00
Nanaloveyuki 6dc54379ea 📝 clarify logger warn helper routing 2026-06-14 11:14:44 +08:00
Nanaloveyuki 458e3a14b3 📝 clarify logger info helper routing 2026-06-14 11:13:07 +08:00
Nanaloveyuki e3c7e00b1e 📝 clarify sync facade unwrap aliasing 2026-06-14 11:11:34 +08:00
Nanaloveyuki 2fd1290179 📝 clarify sync facade projection aliasing 2026-06-14 11:10:04 +08:00
Nanaloveyuki f2b90b44e6 📝 clarify library logger error helper routing 2026-06-14 11:08:13 +08:00
Nanaloveyuki cf2c8cdca6 📝 clarify library logger warn helper routing 2026-06-14 11:06:57 +08:00
Nanaloveyuki 4e964245d5 📝 clarify library logger info helper routing 2026-06-14 11:05:36 +08:00
Nanaloveyuki cc3d1b1f1c 📝 clarify library async info helper routing 2026-06-14 11:04:04 +08:00
Nanaloveyuki e5140181ba 📝 clarify library async warn helper routing 2026-06-14 11:02:51 +08:00
Nanaloveyuki 2bb9b20aa4 📝 clarify library async error helper routing 2026-06-14 11:01:44 +08:00
Nanaloveyuki 32cbc2e079 📝 clarify library async unwrap aliasing 2026-06-14 10:59:58 +08:00
Nanaloveyuki 62117a4a69 📝 clarify async facade projection aliasing 2026-06-14 10:57:48 +08:00
Nanaloveyuki bba206be78 📝 clarify library async target replacement 2026-06-14 10:55:39 +08:00
Nanaloveyuki 22f5204262 📝 clarify library async child facade preservation 2026-06-14 10:53:59 +08:00
Nanaloveyuki 5bb5a75ea7 📝 clarify library async context replacement 2026-06-14 10:50:22 +08:00
Nanaloveyuki 6d1261f02b 📝 clarify async context field replacement 2026-06-14 10:48:37 +08:00
Nanaloveyuki 33fc929dc6 📝 clarify async runtime sink variant selection 2026-06-14 10:46:54 +08:00
Nanaloveyuki c990a890f9 📝 clarify parsed library async sink selection 2026-06-14 10:45:21 +08:00
Nanaloveyuki 676317aae7 📝 clarify parsed application async sink selection 2026-06-14 10:44:00 +08:00
Nanaloveyuki 7f57521e05 📝 clarify application async runtime sink semantics 2026-06-14 10:42:36 +08:00
Nanaloveyuki 9b3533de7b 📝 clarify library async runtime sink semantics 2026-06-14 10:41:01 +08:00
Nanaloveyuki e01f7e977e 📝 clarify library async text sink semantics 2026-06-14 10:39:00 +08:00
Nanaloveyuki 1a2aee4a7c 📝 clarify application text async sink selection 2026-06-14 10:36:40 +08:00
Nanaloveyuki 571ae622d0 📝 clarify async build config stringify routing 2026-06-14 10:33:10 +08:00
Nanaloveyuki 475b15c41f 📝 clarify async build config export routing 2026-06-14 10:31:50 +08:00
Nanaloveyuki 0eeb3f9811 📝 clarify async build config parse routing 2026-06-14 10:30:01 +08:00
Nanaloveyuki 0b8fbe53dd 📝 clarify async build config facade routing 2026-06-14 10:27:22 +08:00
Nanaloveyuki 8dab08b85d 📝 clarify async state alias provenance 2026-06-14 10:22:10 +08:00
Nanaloveyuki 5edd853fc5 📝 clarify async runtime state alias provenance 2026-06-14 10:20:05 +08:00
Nanaloveyuki 5957e37720 📝 clarify async runtime mode probe 2026-06-14 10:18:46 +08:00
Nanaloveyuki 8cf4eba223 📝 clarify async worker capability probe 2026-06-14 10:17:05 +08:00
Nanaloveyuki 754a878cd8 📝 clarify async runtime mode label mapping 2026-06-14 10:15:47 +08:00
Nanaloveyuki 1073559f6a 📝 clarify async runtime constructor inputs 2026-06-14 10:14:31 +08:00
Nanaloveyuki 20e08efb78 📝 clarify async runtime state snapshot source 2026-06-14 10:13:09 +08:00
Nanaloveyuki 64dfc36931 📝 clarify async runtime json snapshot semantics 2026-06-14 10:11:41 +08:00
Nanaloveyuki d46e90fcf5 📝 clarify async state constructor runtime input 2026-06-14 10:10:15 +08:00
Nanaloveyuki 891aa83e01 📝 clarify async state runtime snapshot source 2026-06-14 10:08:57 +08:00
Nanaloveyuki 97f6ae969d 📝 clarify async state json snapshot semantics 2026-06-14 10:07:33 +08:00
Nanaloveyuki 93fc54226d 📝 clarify library async unwrap live state 2026-06-14 10:04:20 +08:00
Nanaloveyuki 4421eb985d 📝 clarify library async shutdown no-worker path 2026-06-14 10:02:48 +08:00
Nanaloveyuki 96c4cc1f88 📝 clarify async shutdown failure retention 2026-06-14 10:01:35 +08:00
Nanaloveyuki 415fc8d98e 📝 clarify async wait_idle failure retention 2026-06-14 10:00:11 +08:00
Nanaloveyuki d89a629f14 📝 clarify async closed state retention 2026-06-14 09:58:55 +08:00
Nanaloveyuki 83c31f31b2 📝 clarify async run restart backlog semantics 2026-06-14 09:57:31 +08:00
Nanaloveyuki 93afc5fe45 📝 clarify library async facade state preservation 2026-06-14 09:56:11 +08:00
Nanaloveyuki a7e9731571 📝 clarify async late log close semantics 2026-06-14 09:54:46 +08:00
Nanaloveyuki 83e1accc8e 📝 clarify async dropped count after failed shutdown 2026-06-14 09:50:25 +08:00
Nanaloveyuki 888581e44a 📝 clarify async pending backlog after failed shutdown 2026-06-14 09:48:17 +08:00
Nanaloveyuki 2ecf88d866 📝 clarify async last error retention after shutdown 2026-06-14 09:46:20 +08:00
Nanaloveyuki 19befe9418 📝 clarify async failure retention after shutdown 2026-06-14 09:42:45 +08:00
Nanaloveyuki dcbc2422c6 📝 clarify async running restart semantics 2026-06-14 09:41:17 +08:00
Nanaloveyuki 5bb34b4e66 📝 clarify async state failure shutdown snapshots 2026-06-14 09:39:34 +08:00
Nanaloveyuki 3fcdf8f64a 📝 clarify async projection preserved failure state 2026-06-14 09:38:00 +08:00
Nanaloveyuki 674e949f96 📝 clarify library async unwrap preserved failure state 2026-06-14 09:36:37 +08:00
Nanaloveyuki bbc9afbc47 📝 clarify library async shutdown failure retention 2026-06-14 09:35:09 +08:00
Nanaloveyuki e386ef8b28 📝 clarify library async run restart semantics 2026-06-14 09:33:24 +08:00
Nanaloveyuki af9e4e853a 📝 clarify async close post-shutdown log split 2026-06-14 09:31:19 +08:00
Nanaloveyuki eb3ec42a59 📝 clarify async flush policy callback semantics 2026-06-14 09:29:16 +08:00
Nanaloveyuki 54fdff3317 📝 clarify async dropped count shutdown split 2026-06-14 09:27:42 +08:00
Nanaloveyuki ded41de176 📝 clarify async logger restart failure semantics 2026-06-14 09:25:56 +08:00
Nanaloveyuki c12af269dc 📝 clarify configured logger composition surface 2026-06-14 09:19:51 +08:00
Nanaloveyuki 03079797f2 📝 clarify async projection runtime helper state 2026-06-14 09:17:38 +08:00
Nanaloveyuki f6fc9c4201 📝 clarify sync projection runtime helper state 2026-06-14 09:15:04 +08:00
Nanaloveyuki d94b415cb0 📝 clarify async runtime builder flush behavior 2026-06-14 09:10:25 +08:00
Nanaloveyuki 4dd1e5a33d 📝 clarify async build config sink-kind semantics 2026-06-14 09:04:38 +08:00
Nanaloveyuki 54e695942f 📝 clarify async build export sink-kind semantics 2026-06-14 09:03:07 +08:00
Nanaloveyuki 4889f2b4b8 📝 clarify text async facade sink-kind behavior 2026-06-14 09:00:52 +08:00
Nanaloveyuki 58d1e622a0 📝 clarify async text builder sink-kind behavior 2026-06-14 08:58:57 +08:00
Nanaloveyuki af1fc95a3c 📝 clarify application helper visibility 2026-06-14 08:52:54 +08:00
Nanaloveyuki 20919618ce 📝 clarify library helper visibility 2026-06-14 08:50:34 +08:00
Nanaloveyuki 35e87f1761 📝 clarify application runtime helper access 2026-06-14 08:48:22 +08:00
Nanaloveyuki 4b043bc52e 📝 clarify application context shape 2026-06-14 08:46:07 +08:00
Nanaloveyuki 296901d2ba 📝 clarify root context shape contrast 2026-06-14 08:43:18 +08:00
Nanaloveyuki c78669393c 📝 clarify async facade context shape 2026-06-14 08:41:06 +08:00
Nanaloveyuki 9162b37acd 📝 clarify root logger target behavior 2026-06-14 08:38:38 +08:00
Nanaloveyuki d777496d51 📝 clarify sync alias target behavior 2026-06-14 08:35:46 +08:00
Nanaloveyuki 44903d113d 📝 clarify async alias target behavior 2026-06-14 08:32:58 +08:00
Nanaloveyuki feb786298f 📝 clarify built async text target behavior 2026-06-14 08:29:26 +08:00
Nanaloveyuki f91bcc827e cover built async text target behavior 2026-06-14 08:28:09 +08:00
Nanaloveyuki da1e9c0359 📝 clarify built async target behavior 2026-06-14 08:22:02 +08:00
Nanaloveyuki acb4a13f14 cover built async target behavior 2026-06-14 08:20:12 +08:00
Nanaloveyuki b320b4f1fc 📝 clarify built sync target behavior 2026-06-14 08:16:52 +08:00
Nanaloveyuki 8715949242 cover built sync target behavior 2026-06-14 08:15:00 +08:00
Nanaloveyuki 70c2bad4b1 📝 clarify parsed configured target behavior 2026-06-14 08:11:41 +08:00
Nanaloveyuki 83b0a2ac3c cover parsed configured target behavior 2026-06-14 08:10:27 +08:00
Nanaloveyuki 5ded4439b0 📝 clarify parsed sync target behavior 2026-06-14 08:08:00 +08:00
Nanaloveyuki 556ee967b8 cover parsed sync target behavior 2026-06-14 08:06:35 +08:00
Nanaloveyuki 72e29f5b69 📝 clarify parsed async target behavior 2026-06-14 08:03:26 +08:00
Nanaloveyuki 57b1dfb127 cover parsed lib async target behavior 2026-06-14 08:01:39 +08:00
Nanaloveyuki 4521961227 cover parsed app async target behavior 2026-06-14 07:58:20 +08:00
Nanaloveyuki a164678654 cover application async target behavior 2026-06-14 07:53:31 +08:00
Nanaloveyuki 50afeacff6 📝 align English README target status 2026-06-14 07:48:40 +08:00
Nanaloveyuki 98e514821f 📝 clarify application async alias behavior 2026-06-14 07:46:24 +08:00
Nanaloveyuki 97feb57cd7 📝 clarify configured logger alias behavior 2026-06-14 07:44:01 +08:00
Nanaloveyuki 9c1787e700 📝 clarify application logger alias behavior 2026-06-14 07:41:51 +08:00
Nanaloveyuki 7ba66e82ae cover sync target override behavior 2026-06-14 07:39:23 +08:00
Nanaloveyuki c316c65027 cover async target override behavior 2026-06-14 07:36:03 +08:00
Nanaloveyuki 4b68ae27f1 📝 clarify async target override docs 2026-06-14 07:34:31 +08:00
Nanaloveyuki 38a5b056b8 📝 clarify async helper combinator docs 2026-06-14 07:25:15 +08:00
Nanaloveyuki f636c2df60 📝 clarify async reshaping helper docs 2026-06-14 07:24:00 +08:00
Nanaloveyuki a66a876659 cover async logger reshaping helpers 2026-06-14 07:22:23 +08:00
Nanaloveyuki f8192ab677 cover async helper combinators 2026-06-14 07:19:59 +08:00
Nanaloveyuki 82200c61fb 📝 align async alias docs 2026-06-14 07:15:46 +08:00
Nanaloveyuki 43e343158e 📝 clarify root async builder docs 2026-06-14 07:14:25 +08:00
Nanaloveyuki 3a2817969a 📝 clarify async text builder docs 2026-06-14 07:12:53 +08:00
Nanaloveyuki 1b508dfc11 📝 clarify async builder equivalence docs 2026-06-14 07:11:32 +08:00
Nanaloveyuki 959e553648 📝 clarify async facade projection docs 2026-06-14 07:09:31 +08:00
Nanaloveyuki 1f3da3e6ba 📝 align async state serializer docs 2026-06-14 07:06:16 +08:00
Nanaloveyuki a2b37dfe53 📝 clarify async state snapshot docs 2026-06-14 07:04:55 +08:00
Nanaloveyuki 6c5f4aaa0e 📝 clarify async failure backlog docs 2026-06-14 07:01:04 +08:00
Nanaloveyuki 3ba590a4b0 📝 clarify async shutdown split docs 2026-06-14 06:58:56 +08:00
Nanaloveyuki 302e11218c 📝 sharpen closed async log docs 2026-06-14 06:57:12 +08:00
Nanaloveyuki b2a1f407ec cover async closed log runtime split 2026-06-14 06:55:48 +08:00
Nanaloveyuki 24c20c16be 📝 narrow async facade semantics docs 2026-06-14 06:53:17 +08:00
Nanaloveyuki 254a9e8086 cover async text shutdown flush path 2026-06-14 06:51:27 +08:00
Nanaloveyuki 0d2bfd7b6d cover async text batch flush path 2026-06-14 06:49:05 +08:00
Nanaloveyuki b570722434 📝 clarify text async flush docs 2026-06-14 06:44:51 +08:00
Nanaloveyuki 58e219a512 cover parsed lib clear shutdown 2026-06-14 06:40:06 +08:00
Nanaloveyuki 88ee050529 cover parsed app clear shutdown 2026-06-14 06:38:18 +08:00
Nanaloveyuki 6962c7f267 cover lib async clear shutdown 2026-06-14 06:35:14 +08:00
Nanaloveyuki e91aba10fc cover app async clear shutdown 2026-06-14 06:33:29 +08:00
Nanaloveyuki 74f65b9585 cover lib text clear shutdown 2026-06-14 06:31:07 +08:00
Nanaloveyuki 5f722b0073 cover app text clear shutdown 2026-06-14 06:28:54 +08:00
Nanaloveyuki fd9127c524 cover app text async composition 2026-06-14 06:24:17 +08:00
Nanaloveyuki 057eb7c1fc cover parsed app async composition 2026-06-14 06:20:56 +08:00
Nanaloveyuki 24897a45c9 cover app text alias sink-kind path 2026-06-14 06:17:00 +08:00
Nanaloveyuki 9370c83ffc cover async facade clear shutdown 2026-06-14 06:13:06 +08:00
Nanaloveyuki 3a2d1d74c3 cover async text facade sink-kind path 2026-06-14 06:08:58 +08:00
Nanaloveyuki ef4ffe4c5b cover async projection file parity 2026-06-14 06:05:34 +08:00
Nanaloveyuki f69307ba61 cover async library file parity 2026-06-14 05:57:05 +08:00
Nanaloveyuki 2582876a08 cover async application file parity 2026-06-14 05:52:23 +08:00
Nanaloveyuki bf60ed95c3 cover projected file helper parity 2026-06-14 05:48:20 +08:00
Nanaloveyuki 39baad5e93 cover library file control parity 2026-06-14 05:45:54 +08:00
Nanaloveyuki 383d2e8dff cover library file helper parity 2026-06-14 05:43:33 +08:00
Nanaloveyuki b57013202e cover parse-build invalid json parity 2026-06-14 05:40:51 +08:00
Nanaloveyuki 13e8a8f484 cover application file control parity 2026-06-14 05:38:44 +08:00
Nanaloveyuki 3cd361dc4d cover application file helper parity 2026-06-14 05:36:19 +08:00
Nanaloveyuki c262aefc28 cover configured file state parity 2026-06-14 05:33:39 +08:00
Nanaloveyuki a195c93457 cover configured file reset parity 2026-06-14 05:28:52 +08:00
Nanaloveyuki efacaa6398 cover configured reopen parity 2026-06-14 05:27:09 +08:00
Nanaloveyuki af54743536 cover configured file setter parity 2026-06-14 05:25:32 +08:00
Nanaloveyuki 8d28c37e38 cover configured file policy parity 2026-06-14 05:23:56 +08:00
Nanaloveyuki c2fa1eea35 cover configured file close parity 2026-06-14 05:21:19 +08:00
Nanaloveyuki d2612e5a67 cover configured file helper parity 2026-06-14 05:19:55 +08:00
Nanaloveyuki 49eaa67d57 cover configured close delegation 2026-06-14 05:17:55 +08:00
Nanaloveyuki 6d98301daa cover configured helper delegation 2026-06-14 05:16:34 +08:00
Nanaloveyuki 5f46c04eea cover async text application parity 2026-06-14 05:14:11 +08:00
Nanaloveyuki b36ce021dc cover async text library parity 2026-06-14 05:12:19 +08:00
Nanaloveyuki ead2339ffd cover async library parse-build parity 2026-06-14 05:10:13 +08:00
Nanaloveyuki cca3bc4500 cover async library builder parity 2026-06-14 05:08:23 +08:00
Nanaloveyuki 9d55440df4 cover sync library parse-build parity 2026-06-14 05:06:08 +08:00
Nanaloveyuki 4077f3e538 cover sync library builder parity 2026-06-14 05:04:38 +08:00
Nanaloveyuki 658196cf69 cover sync parse-build parity 2026-06-14 05:03:02 +08:00
Nanaloveyuki afe5c75537 cover async parse-build parity 2026-06-14 05:01:42 +08:00
Nanaloveyuki 2c552adfae cover async application builder parity 2026-06-14 04:59:41 +08:00
Nanaloveyuki 1f61e4f66a cover sync application builder parity 2026-06-14 04:57:42 +08:00
Nanaloveyuki b68ca9eef5 cover sync config export defaults 2026-06-14 04:51:52 +08:00
Nanaloveyuki 9da5b9d659 cover async build-config export defaults 2026-06-14 04:50:09 +08:00
Nanaloveyuki e97407c22c cover sync nested parser defaults 2026-06-14 04:47:21 +08:00
Nanaloveyuki 41fbfa5ac1 cover sync parser defaults 2026-06-14 04:45:43 +08:00
Nanaloveyuki 5c4e8ba889 cover async text builder sink contract 2026-06-14 04:44:18 +08:00
Nanaloveyuki c96a592ef6 cover async build-config defaults 2026-06-14 04:39:40 +08:00
Nanaloveyuki eb4abeb81b cover async parser aliases 2026-06-14 04:34:18 +08:00
Nanaloveyuki e2609a99b6 cover async config normalization 2026-06-14 04:28:29 +08:00
Nanaloveyuki 2709a482ec cover async parse-build failures 2026-06-14 04:21:15 +08:00
Nanaloveyuki 999dd5a297 cover sync parse-build config errors 2026-06-14 04:16:42 +08:00
Nanaloveyuki bd75deb879 cover runtime file json helpers 2026-06-14 04:11:57 +08:00
Nanaloveyuki db5d95576d cover config json helper exports 2026-06-14 04:08:18 +08:00
Nanaloveyuki f4af7bc04c cover async json helper exports 2026-06-14 04:06:23 +08:00
Nanaloveyuki 8ce3b8fefd cover direct async text builder surface 2026-06-14 03:59:06 +08:00
Nanaloveyuki da8e7483ed cover direct async builder surface 2026-06-14 03:55:41 +08:00
Nanaloveyuki e617f5bf6a 🔖 bump version to 0.5.3 2026-06-14 03:53:17 +08:00
Nanaloveyuki 9042562c54 🔖 prepare 0.5.3 release notes 2026-06-14 03:50:23 +08:00
Nanaloveyuki 4c5b6cc2cf cover library async text helpers 2026-06-14 03:44:21 +08:00
Nanaloveyuki 1bb3e41a97 cover parsed library async helpers 2026-06-14 03:42:28 +08:00
Nanaloveyuki 03e467d5f4 cover parsed application async helpers 2026-06-14 03:40:31 +08:00
Nanaloveyuki 8c129e1c42 cover parsed library logger unwrap 2026-06-14 03:35:52 +08:00
Nanaloveyuki a7e955e636 cover parsed application logger helpers 2026-06-14 03:34:09 +08:00
Nanaloveyuki 2eebef07db cover parsed configured logger surface 2026-06-14 03:32:39 +08:00
Nanaloveyuki 594be4aca5 cover configured logger composition 2026-06-14 03:30:18 +08:00
Nanaloveyuki 9157346bf8 cover application alias composition 2026-06-14 03:26:36 +08:00
Nanaloveyuki 7474c07cbd cover application text async alias 2026-06-14 03:23:03 +08:00
Nanaloveyuki 11db21a500 cover application alias helper surface 2026-06-14 03:21:09 +08:00
Nanaloveyuki 17dbdfffde cover library async constructor contract 2026-06-14 03:18:06 +08:00
Nanaloveyuki a41515b8eb cover library async write facade 2026-06-14 03:15:44 +08:00
Nanaloveyuki 2f600c71c5 cover library async target facade 2026-06-14 03:13:45 +08:00
Nanaloveyuki e6dc5f52c0 cover library async context facade 2026-06-14 03:11:34 +08:00
Nanaloveyuki 7a0c741857 cover default library logger snapshot 2026-06-14 03:07:46 +08:00
Nanaloveyuki e3b9cbb6e9 cover library logger write facade 2026-06-14 03:06:14 +08:00
Nanaloveyuki 264ee05222 cover library logger target facade 2026-06-14 03:04:23 +08:00
Nanaloveyuki 9ef2f984ca cover library logger context facade 2026-06-14 03:02:47 +08:00
Nanaloveyuki 6a13f70242 📝 clarify library logger runtime unwrap 2026-06-14 02:58:58 +08:00
Nanaloveyuki c767ebe512 📝 refresh wasm-gc sync verification note 2026-06-14 02:54:20 +08:00
Nanaloveyuki 402cb7e423 📝 refresh wasm sync verification note 2026-06-14 02:52:38 +08:00
Nanaloveyuki 24fbc189ae 📝 refresh js sync verification note 2026-06-14 02:51:19 +08:00
Nanaloveyuki 935f320743 📝 refresh wasm async verification note 2026-06-14 02:49:52 +08:00
Nanaloveyuki d288216bcb 📝 refresh async target verification note 2026-06-14 02:48:30 +08:00
Nanaloveyuki c3b54e3ae0 align async facade test across targets 2026-06-14 02:47:06 +08:00
Nanaloveyuki 413610d5f2 cover async facade state projection 2026-06-14 02:45:15 +08:00
Nanaloveyuki 33f71af500 📝 clarify queued file failure docs 2026-06-14 02:42:37 +08:00
Nanaloveyuki f7863083d4 cover runtime file reopen helpers 2026-06-14 02:40:35 +08:00
Nanaloveyuki fcac1d7993 cover runtime file helper contracts 2026-06-14 02:37:56 +08:00
Nanaloveyuki 0bdbe942dd cover runtime sink helper contracts 2026-06-14 02:35:27 +08:00
Nanaloveyuki 1645bcb66c cover parsed async queue wrappers 2026-06-14 02:30:41 +08:00
Nanaloveyuki 112edbf8ae cover direct text async builder queue path 2026-06-14 02:28:46 +08:00
Nanaloveyuki 8084d0a0cc cover library text async builder path 2026-06-14 02:27:05 +08:00
Nanaloveyuki d23e326315 cover application text async builder path 2026-06-14 02:25:11 +08:00
Nanaloveyuki e38b0b4150 cover application async builder queue path 2026-06-14 02:22:49 +08:00
Nanaloveyuki ce89aaf96d cover library async failure flow 2026-06-14 02:19:40 +08:00
Nanaloveyuki c53aa38b89 cover async shutdown failure path 2026-06-14 02:17:23 +08:00
Nanaloveyuki 3e0c8a5f99 cover async retry reset behavior 2026-06-14 02:14:49 +08:00
Nanaloveyuki f1250512eb 📝 clarify async status helper docs 2026-06-14 02:11:26 +08:00
Nanaloveyuki 26de2e81d6 📝 refine async state snapshot docs 2026-06-14 02:09:29 +08:00
Nanaloveyuki 9af489336d 🐛 fix closed async backlog accounting 2026-06-14 02:06:59 +08:00
Nanaloveyuki d9b609d064 📝 clarify async lifecycle docs 2026-06-14 02:03:34 +08:00
Nanaloveyuki 91b0900b11 📝 refine async snapshot docs 2026-06-14 01:59:27 +08:00
Nanaloveyuki e13ea2209a 📝 clarify async config type docs 2026-06-14 01:58:06 +08:00
Nanaloveyuki 034bd8fc99 📝 clarify async policy docs 2026-06-14 01:56:44 +08:00
Nanaloveyuki c911ad8345 📝 refine async runtime helper docs 2026-06-14 01:55:23 +08:00
Nanaloveyuki e776455861 📝 refine async state type docs 2026-06-14 01:53:12 +08:00
Nanaloveyuki f824cbfa68 📝 clarify async state export docs 2026-06-14 01:50:30 +08:00
Nanaloveyuki abed0f00b8 📝 refine async config parser docs 2026-06-14 01:48:35 +08:00
Nanaloveyuki 75f1b457fa 📝 clarify async config export docs 2026-06-14 01:47:02 +08:00
Nanaloveyuki e53555edb2 📝 clarify formatter export docs 2026-06-14 01:45:18 +08:00
Nanaloveyuki 323d58059b 📝 refine formatter config docs 2026-06-14 01:43:27 +08:00
Nanaloveyuki 8e409bbdf9 📝 refine config stringify docs 2026-06-14 01:42:16 +08:00
Nanaloveyuki b3fb59e6b5 📝 clarify config export docs 2026-06-14 01:41:02 +08:00
Nanaloveyuki a6e9dd993f 📝 refine config helper docs 2026-06-14 01:39:40 +08:00
Nanaloveyuki 324ff47b10 📝 clarify config model docs 2026-06-14 01:38:16 +08:00
Nanaloveyuki 8bf6ec8f52 📝 refine config entry docs 2026-06-14 01:36:33 +08:00
Nanaloveyuki bf545b0e0c 📝 clarify default logger docs 2026-06-14 01:35:25 +08:00
Nanaloveyuki d4db20fffc 📝 clarify library builder docs 2026-06-14 01:34:08 +08:00
Nanaloveyuki 861adb7b5d 📝 refine sync parse builder docs 2026-06-14 01:33:06 +08:00
Nanaloveyuki 1a33f5c95d 📝 refine async parse builder docs 2026-06-14 01:31:32 +08:00
Nanaloveyuki f50964f5a9 📝 clarify async text builder docs 2026-06-14 01:30:22 +08:00
Nanaloveyuki ba72a021a8 📝 align async logger root docs 2026-06-14 01:28:23 +08:00
Nanaloveyuki 5f0c7be4e4 📝 clarify app text async docs 2026-06-14 01:24:48 +08:00
Nanaloveyuki 4d2e3def14 📝 align facade overview docs 2026-06-14 01:23:15 +08:00
Nanaloveyuki 2a9dbdcc01 📝 clarify app logger facade docs 2026-06-14 01:21:42 +08:00
Nanaloveyuki 47de8dc99a 📝 refine library logger entry docs 2026-06-14 01:20:04 +08:00
Nanaloveyuki 888be5b6fc 📝 refine library logger write docs 2026-06-14 01:18:33 +08:00
Nanaloveyuki 15a9175cf4 📝 refine library logger wrapper methods 2026-06-14 01:16:36 +08:00
Nanaloveyuki 3a68be920e 📝 clarify library logger wrapper docs 2026-06-14 01:14:45 +08:00
Nanaloveyuki 699dd5ff96 📝 refine library async lifecycle docs 2026-06-14 01:11:52 +08:00
Nanaloveyuki f8ca093e95 📝 refine library async write docs 2026-06-14 01:10:10 +08:00
Nanaloveyuki be8b4f8626 📝 refine library async wrapper methods 2026-06-14 01:08:21 +08:00
Nanaloveyuki 3d88ac87a1 📝 clarify library async wrapper docs 2026-06-14 01:06:15 +08:00
Nanaloveyuki 79529d748f 📝 clarify app async build docs 2026-06-14 01:04:11 +08:00
Nanaloveyuki ab7cd62851 📝 refine library async build docs 2026-06-14 01:02:23 +08:00
Nanaloveyuki e172e141e9 📝 align async facade builders 2026-06-14 00:57:38 +08:00
Nanaloveyuki d92155a727 📝 align async text facade docs 2026-06-14 00:56:01 +08:00
Nanaloveyuki 78007a5b22 📝 align async facade docs 2026-06-14 00:54:13 +08:00
Nanaloveyuki e28dba0800 📝 clarify async logger root docs 2026-06-14 00:52:34 +08:00
Nanaloveyuki 747f8e3d1b 📝 refine async run docs 2026-06-14 00:50:55 +08:00
Nanaloveyuki 5917256fda 📝 refine async shutdown docs 2026-06-14 00:48:44 +08:00
Nanaloveyuki b937807136 📝 clarify async backlog docs 2026-06-14 00:47:07 +08:00
Nanaloveyuki 5ce4c29760 📝 refine async failure helper docs 2026-06-14 00:45:31 +08:00
Nanaloveyuki 911dcd840c 📝 align async logger state docs 2026-06-14 00:43:50 +08:00
Nanaloveyuki 4431e01dcb 📝 align async runtime serialization docs 2026-06-14 00:41:09 +08:00
Nanaloveyuki d950f11b40 📝 clarify async runtime snapshots 2026-06-14 00:38:07 +08:00
Nanaloveyuki 2845076b27 📝 refine async policy docs 2026-06-14 00:33:59 +08:00
Nanaloveyuki 7207c07cbf 📝 clarify async config docs 2026-06-14 00:32:05 +08:00
Nanaloveyuki f19e9649af 📝 align async build config docs 2026-06-14 00:29:22 +08:00
Nanaloveyuki c45ee1050f 📝 clarify async build config consumers 2026-06-14 00:27:38 +08:00
Nanaloveyuki d748bfc6e6 📝 clarify async text builder path 2026-06-14 00:23:06 +08:00
Nanaloveyuki 77d97cef5e 📝 align async facade builder docs 2026-06-14 00:20:44 +08:00
Nanaloveyuki 3888d39bc0 📝 clarify async builder layering docs 2026-06-14 00:18:58 +08:00
Nanaloveyuki f7febb9f67 📝 fix async constructor signature docs 2026-06-14 00:16:08 +08:00
Nanaloveyuki 7440f1d328 📝 align remaining async examples 2026-06-14 00:14:19 +08:00
Nanaloveyuki e035625fc1 📝 align async write examples 2026-06-14 00:12:51 +08:00
Nanaloveyuki dae9d38a3f 📝 align async lifecycle examples 2026-06-14 00:10:59 +08:00
Nanaloveyuki ab45a9e4e3 📝 fix async alias examples 2026-06-14 00:09:42 +08:00
Nanaloveyuki e27f5680e6 📝 clarify async shutdown runtime docs 2026-06-14 00:08:24 +08:00
Nanaloveyuki 8196fe27b6 📝 clarify async text builder docs 2026-06-14 00:06:05 +08:00
Nanaloveyuki 4b5456f646 📝 clarify async library facade scope 2026-06-14 00:04:02 +08:00
Nanaloveyuki f4022ce95c 📝 clarify library facade runtime scope 2026-06-14 00:01:39 +08:00
300 changed files with 9757 additions and 16586 deletions
+44 -168
View File
@@ -7,198 +7,74 @@ on:
pull_request:
jobs:
quality-matrix:
name: Quality (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
moonbit:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup MoonBit (Linux/macOS)
if: runner.os != 'Windows'
shell: bash
- name: Install MoonBit
run: |
curl -fsSL https://cli.moonbitlang.com/install/unix.sh | bash
echo "$HOME/.moon/bin" >> "$GITHUB_PATH"
- name: Setup MoonBit (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
irm https://cli.moonbitlang.com/install/powershell.ps1 | iex
"$HOME/.moon/bin" | Out-File -FilePath $env:GITHUB_PATH -Append
- name: Setup MSYS2 toolchain (Windows)
if: runner.os == 'Windows'
uses: msys2/setup-msys2@v2
with:
msystem: UCRT64
update: true
install: >-
mingw-w64-ucrt-x86_64-gcc
mingw-w64-ucrt-x86_64-openssl
- name: Show tool versions
shell: bash
run: |
moon version --all
moon version
- name: Update Moon registry
shell: bash
run: |
moon update
- name: Check formatting and exported interfaces
shell: bash
- name: Check bitlogger
run: |
moon fmt --check
moon info
git diff --exit-code
moon check
- name: Root checks and tests
shell: bash
- name: Test bitlogger
run: |
moon check --deny-warn
moon test --deny-warn
moon check --target native --deny-warn
moon check --target wasm --deny-warn
moon check --target wasm-gc --deny-warn
moon check --target js --deny-warn
moon test
- name: Test wasm path
shell: bash
- name: Check bitlogger native
run: |
moon test --target wasm --deny-warn
moon check --target native
- name: Run sync example
shell: bash
- name: Check bitlogger wasm-gc
run: |
moon check --target wasm-gc
- name: Check bitlogger js
run: |
moon check --target js
- name: Check bitlogger_async native
run: |
moon check src-async --target native
- name: Check bitlogger_async wasm-gc
run: |
moon check src-async --target wasm-gc
- name: Check bitlogger_async js
run: |
moon check src-async --target js
- name: Test bitlogger_async native
run: |
moon test src-async --target native
- name: Test bitlogger_async wasm-gc
run: |
moon test src-async --target wasm-gc
- name: Test bitlogger_async js
run: |
moon test src-async --target js
- name: Run basic example
run: |
moon run examples/basic
- name: Check async example native
if: runner.os != 'Windows'
shell: bash
run: |
moon check examples/async_basic --target native --deny-warn
async-cross-targets:
name: Async cross-targets (Ubuntu)
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup MoonBit
shell: bash
run: |
curl -fsSL https://cli.moonbitlang.com/install/unix.sh | bash
echo "$HOME/.moon/bin" >> "$GITHUB_PATH"
- name: Show tool versions
shell: bash
run: |
moon version --all
- name: Update Moon registry
shell: bash
run: |
moon update
- name: Check async package on wasm, wasm-gc and js
shell: bash
run: |
moon check src-async --target wasm --deny-warn
moon check src-async --target wasm-gc --deny-warn
moon check src-async --target js --deny-warn
- name: Test async package on wasm, wasm-gc and js
shell: bash
run: |
moon test src-async --target wasm --deny-warn
moon test src-async --target wasm-gc --deny-warn
moon test src-async --target js --deny-warn
async-native:
name: Async native (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup MoonBit
shell: bash
run: |
curl -fsSL https://cli.moonbitlang.com/install/unix.sh | bash
echo "$HOME/.moon/bin" >> "$GITHUB_PATH"
- name: Show tool versions
shell: bash
run: |
moon version --all
- name: Update Moon registry
shell: bash
run: |
moon update
- name: Check async native path
shell: bash
run: |
moon check src-async --target native --deny-warn
- name: Test async native path
shell: bash
run: |
moon test src-async --target native --deny-warn
coverage:
name: Coverage (Ubuntu)
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup MoonBit
shell: bash
run: |
curl -fsSL https://cli.moonbitlang.com/install/unix.sh | bash
echo "$HOME/.moon/bin" >> "$GITHUB_PATH"
- name: Show tool versions
shell: bash
run: |
moon version --all
- name: Update Moon registry
shell: bash
run: |
moon update
- name: Root coverage (default target)
shell: bash
run: |
moon coverage clean
moon test --deny-warn --enable-coverage
moon coverage report -f summary
moon coverage analyze
- name: Root coverage (native target)
shell: bash
run: |
moon coverage clean
moon test --deny-warn --target native --enable-coverage
moon coverage report -f summary
moon coverage analyze
moon check examples/async_basic --target native
-3
View File
@@ -26,8 +26,5 @@ docs/.vitepress/cache/
docs/.vitepress/dist/
docs/.vitepress/generated/
# Benchmark package has no public API; moon info emits an empty snapshot.
benchmarks/pkg.generated.mbti
# vibecoding
AGENTS/
-26
View File
@@ -1,26 +0,0 @@
# Agent Notes
## Version Releases
Do not update package versions and installation snippets by hand. Run the
repository release helper from the root instead:
```powershell
.\scripts\update-version.ps1 <x.x.x>
```
For a normal patch release, the script updates `moon.mod`, all current
installation examples, creates the next `docs/changes/<release>(<version>).md`,
and adds it to `docs/changes/index.md`. Review and replace any generated `TODO`
entries in the release note before committing.
For a major or minor package-version change, supply the public release number
explicitly so it is not inferred:
```powershell
.\scripts\update-version.ps1 <x.x.x> -ReleaseVersion <x.x.x>
```
Use `-WhatIf` to preview the target files. Pass `-Change`, `-Verification`,
and `-Note` to populate release-note sections directly. Validate the edited
repository before committing with a `gitmoji + short desc` message.
+30 -46
View File
@@ -4,58 +4,35 @@ BitLogger 是一个使用 MoonBit 编写的结构化日志库,适合命令行
- [Mooncake 文档页](https://mooncakes.io/docs/Nanaloveyuki/BitLogger)
- [English README](./docs/README-en.md)
- [Wiki](https://bitlogger.naloveyuki.top)
## 从第一个日志到扩展能力
## 介绍
BitLogger 的文档按使用路径组织:先完成一个可运行的日志输出,再按需进入文件、配置、异步和组合能力。API 文档保留为精确参考,不需要从 API 文件名开始阅读
BitLogger 提供统一的日志级别、目标名、结构化字段和可定制格式,既可以直接输出到控制台,也可以在 native 环境写入文件,并提供异步日志版本
### 1. 安装
从一个空项目开始:
```bash
moon new log-demo
cd log-demo
moon add Nanaloveyuki/BitLogger@0.7.3
```
### 2. 写入第一条结构化日志
在应用 package 的 `moon.pkg` 中导入库:
## 快速开始
```moonbit
import {
"Nanaloveyuki/BitLogger/src" @log,
}
let logger = build_logger(
text_console(
min_level=Level::Info,
target="demo",
text_formatter=TextFormatterConfig::new(show_timestamp=false, separator=" | "),
),
)
logger.info("starting", fields=[field("port", "8080")])
ignore(logger.flush())
```
然后在 `main.mbt` 中创建控制台 logger
推荐从 `console(...)``json_console(...)``text_console(...)``file(...)` 这几个入口开始,再按需配合 `with_queue(...)``with_file_rotation(...)`
```moonbit
fn main {
let logger = @log.build_logger(
@log.console(min_level=@log.Level::Info, target="app"),
)
logger.info("server started", fields=[
@log.field("port", "8080"),
@log.field("environment", "development"),
])
}
```
运行 `moon run` 后,记录会携带 level、target、message 和 fields。下一步按实际需求选择:
- [控制台与结构化字段](./docs/examples/console.md)
- [文件输出与轮转](./docs/examples/file-rotation.md)
- [JSON 配置构建](./docs/examples/config.md)
- [异步日志生命周期](./docs/examples/async.md)
如果你需要自己组合 sink,比如 `fanout``split``callback`,再使用 `Logger::new(...)`
## 支持情况
- `BitLogger` 当前在 CI 中检查/验证的目标是 `native``wasm``js``wasm-gc`
- `bitlogger_async` 当前在 CI 中检查和测试 `native``wasm``js``wasm-gc`
- `BitLogger` 当前在 CI 中检查/验证的目标是 `native``js``wasm-gc`
- `bitlogger_async` 当前在 CI 中检查 `native``js``wasm-gc`,测试覆盖 `native``js``wasm-gc`
- `wasm` 目标在源码 `moon.pkg` 中保留声明,但当前未纳入 CI 验证口径
- `llvm` 目前按实验性目标处理,当前环境未完成验证
- 文件输出是 native 能力;跨端代码里建议先判断 `native_files_supported()`
- `src-async` 可用,但示例 `examples/async_basic` 目前仍按 native 入口提供
@@ -68,13 +45,20 @@ fn main {
- 配置驱动构建:`build_logger(...)``build_async_logger(...)`
- 组合能力:queue、filter、patch、fanout、split、callback
- 异步日志:独立 `src-async` package
- Trace context:标准 `trace_id``span_id``trace_flags``trace_state` 字段绑定
## 示例
- `examples/console_basic/`:最小 console / json console 示例
- `examples/text_formatter/`:文本格式与模板示例
- `examples/style_tags/`style tag 与彩色输出示例
- `examples/config_build/`:配置构建示例
- `examples/presets/`:常用预设组合示例
- `examples/file_rotation/`:文件输出与轮转示例,仅适用于 native
- `examples/async_basic/`:异步日志示例
## 文档
- [Examples:完整使用流程](./docs/examples/index.md)
- [Extend:队列、组合、格式化和跨端边界](./docs/extend/index.md)
- [API 索引:按公开符号查询](./docs/api/index.md)
- [API 索引](./docs/api/index.md)
- [src package README](./src/README.mbt.md)
仓库内的 `examples/` 目录与 Examples 文档一一对应;文档解释选择、前提、运行命令和后续扩展,源码保持为可执行参考。
常用入口:`text_console(...)``file(...)``with_queue(...)``build_logger(...)``build_async_logger(...)`
-11
View File
@@ -1,11 +0,0 @@
# BitLogger Benchmarks
Run the native baseline from the repository root:
```powershell
moon bench benchmarks --target native --release --deny-warn
```
The suite measures callback emission, trace-context field binding, synchronous queue enqueue-and-flush, and native file writes. It intentionally has no pass/fail threshold: compare results only on the same machine, toolchain, target, and power profile.
Async throughput remains lifecycle-sensitive and is exercised by the native integration test rather than mixed into these synchronous microbenchmarks. Record its end-to-end measurements separately when profiling an application workload.
-61
View File
@@ -1,61 +0,0 @@
///|
let benchmark_record : @log.Record = @log.Record::new(
@log.Level::Info,
"benchmark record",
target="bench",
fields=[@log.field("component", "bitlogger")],
)
///|
test "bench callback logger emission" (it : @bench.T) {
let writes : Ref[Int] = Ref(0)
let logger = @log.Logger::new(@log.callback_sink(fn(_) { writes.val += 1 }))
it.bench(fn() {
logger.info("benchmark record", fields=[
@log.field("component", "bitlogger"),
])
it.keep(writes.val)
})
}
///|
test "bench trace context field binding" (it : @bench.T) {
let writes : Ref[Int] = Ref(0)
let context = @log.trace_context("trace-bench", "span-bench")
let logger = @log.Logger::new(@log.callback_sink(fn(_) { writes.val += 1 })).with_trace_context(
context,
)
it.bench(fn() {
logger.info("benchmark record", fields=[@log.field("event", "request")])
it.keep(writes.val)
})
}
///|
test "bench queued logger enqueue and flush" (it : @bench.T) {
let writes : Ref[Int] = Ref(0)
let logger = @log.Logger::new(@log.callback_sink(fn(_) { writes.val += 1 })).with_queue(
max_pending=8,
)
it.bench(fn() {
logger.info("benchmark record")
it.keep(logger.sink.flush())
})
}
///|
test "bench native file sink write" (it : @bench.T) {
let sink = @log.file_sink(
"logs/bitlogger-benchmark.log",
append=false,
auto_flush=false,
formatter=fn(rec) { rec.message },
)
if sink.is_available() {
it.bench(fn() {
sink.write(benchmark_record)
it.keep(sink.write_failures())
})
ignore(sink.close())
}
}
-4
View File
@@ -1,4 +0,0 @@
import {
"Nanaloveyuki/BitLogger/src" @log,
"moonbitlang/core/bench",
}
+22 -124
View File
@@ -104,119 +104,6 @@ function buildChangesSidebar(): DefaultTheme.SidebarItem[] {
]
}
function buildExamplesSidebar(): DefaultTheme.SidebarItem[] {
return [
{ text: 'Overview', link: '/examples/' },
{ text: 'Console And Fields', link: '/examples/console' },
{ text: 'File Rotation', link: '/examples/file-rotation' },
{ text: 'Configuration', link: '/examples/config' },
{ text: 'Async Lifecycle', link: '/examples/async' },
]
}
function buildExtendSidebar(): DefaultTheme.SidebarItem[] {
return [
{ text: 'Overview', link: '/extend/' },
{ text: 'Queueing', link: '/extend/queue' },
{ text: 'Sink Composition', link: '/extend/composition' },
{ text: 'Text Formatting', link: '/extend/formatting' },
{ text: 'Target Boundaries', link: '/extend/targets' },
{ text: 'Trace Context', link: '/extend/observability' },
]
}
function buildChineseExamplesSidebar(): DefaultTheme.SidebarItem[] {
return [
{ text: '概览', link: '/zh/examples/' },
{ text: '控制台与结构化字段', link: '/zh/examples/console' },
{ text: '文件输出与轮转', link: '/zh/examples/file-rotation' },
{ text: '配置驱动构建', link: '/zh/examples/config' },
{ text: '异步日志生命周期', link: '/zh/examples/async' },
]
}
function buildChineseExtendSidebar(): DefaultTheme.SidebarItem[] {
return [
{ text: '概览', link: '/zh/extend/' },
{ text: '队列与溢出策略', link: '/zh/extend/queue' },
{ text: 'Sink 组合', link: '/zh/extend/composition' },
{ text: '文本格式与样式', link: '/zh/extend/formatting' },
{ text: '目标平台边界', link: '/zh/extend/targets' },
{ text: 'Trace Context', link: '/zh/extend/observability' },
]
}
function buildChineseApiSidebar(): DefaultTheme.SidebarItem[] {
return [
{ text: '概览', link: '/zh/api/' },
{ text: '基础记录', link: '/zh/api/basics' },
{ text: '配置与队列', link: '/zh/api/configuration' },
{ text: '文件输出', link: '/zh/api/file-output' },
{ text: '文本格式', link: '/zh/api/formatting' },
{ text: '异步生命周期', link: '/zh/api/async' },
{ text: 'Sink 组合', link: '/zh/api/composition' },
]
}
const englishThemeConfig: DefaultTheme.Config = {
siteTitle: 'BitLogger',
nav: [
{ text: 'Home', link: '/' },
{ text: 'Examples', link: '/examples/' },
{ text: 'Extend', link: '/extend/' },
{ text: 'API', link: '/api/' },
{ text: 'Changes', link: '/changes/' },
{ text: 'Mooncake', link: 'https://mooncakes.io/docs/Nanaloveyuki/BitLogger' },
],
search: {
provider: 'local',
},
socialLinks: [{ icon: 'github', link: repository }],
editLink: {
pattern: `${repository}/edit/main/docs/:path`,
text: 'Edit this page on GitHub',
},
sidebar: {
'/examples/': buildExamplesSidebar(),
'/extend/': buildExtendSidebar(),
'/api/': buildApiSidebar(),
'/changes/': buildChangesSidebar(),
},
footer: {
message: 'Published from the repository docs folder with VitePress.',
copyright: 'MIT',
},
}
const chineseThemeConfig: DefaultTheme.Config = {
siteTitle: 'BitLogger',
nav: [
{ text: '首页', link: '/zh/' },
{ text: '示例', link: '/zh/examples/' },
{ text: '扩展', link: '/zh/extend/' },
{ text: 'API', link: '/zh/api/' },
{ text: '更新记录(英文)', link: '/changes/' },
{ text: 'Mooncake', link: 'https://mooncakes.io/docs/Nanaloveyuki/BitLogger' },
],
search: {
provider: 'local',
},
socialLinks: [{ icon: 'github', link: repository }],
editLink: {
pattern: `${repository}/edit/main/docs/:path`,
text: '在 GitHub 上编辑此页',
},
sidebar: {
'/zh/examples/': buildChineseExamplesSidebar(),
'/zh/extend/': buildChineseExtendSidebar(),
'/zh/api/': buildChineseApiSidebar(),
},
footer: {
message: '由仓库中的 VitePress 文档构建。',
copyright: 'MIT',
},
}
export default defineConfig({
title: 'BitLogger',
description: 'Structured logging library docs for MoonBit.',
@@ -227,18 +114,29 @@ export default defineConfig({
markdown: {
languages: [createMoonbitLanguageRegistration()],
},
themeConfig: englishThemeConfig,
locales: {
root: {
label: 'English',
lang: 'en-US',
themeConfig: englishThemeConfig,
themeConfig: {
siteTitle: 'BitLogger',
nav: [
{ text: 'Home', link: '/' },
{ text: 'API', link: '/api/' },
{ text: 'Changes', link: '/changes/' },
{ text: 'Mooncake', link: 'https://mooncakes.io/docs/Nanaloveyuki/BitLogger' },
],
search: {
provider: 'local',
},
zh: {
label: '简体中文',
lang: 'zh-CN',
link: '/zh/',
themeConfig: chineseThemeConfig,
socialLinks: [{ icon: 'github', link: repository }],
editLink: {
pattern: `${repository}/edit/main/docs/:path`,
text: 'Edit this page on GitHub',
},
sidebar: {
'/api/': buildApiSidebar(),
'/changes/': buildChangesSidebar(),
},
footer: {
message: 'Published from the repository docs folder with VitePress.',
copyright: 'MIT',
},
},
})
+1 -36
View File
@@ -6,46 +6,11 @@ import HomeDocHub from './components/HomeDocHub.vue'
import './custom.css'
const localePreferenceKey = 'bitlogger-docs-locale'
function routePath(path: string): string {
return path.split(/[?#]/, 1)[0]
}
function isLocaleRoot(path: string): boolean {
const normalized = routePath(path)
return normalized === '/' || normalized === '/zh/'
}
function browserPrefersChinese(): boolean {
return navigator.languages.some(language => language.toLowerCase().startsWith('zh'))
}
const theme: Theme = {
extends: DefaultTheme,
enhanceApp({ app, router }) {
enhanceApp({ app }) {
app.component('ApiOverview', ApiOverview)
app.component('HomeDocHub', HomeDocHub)
if (typeof window === 'undefined') return
router.onAfterRouteChange = to => {
if (!isLocaleRoot(to)) return
window.localStorage.setItem(localePreferenceKey, routePath(to) === '/zh/' ? 'zh' : 'en')
}
if (router.route.path !== '/') return
const savedLocale = window.localStorage.getItem(localePreferenceKey)
const locale = savedLocale === 'zh' || savedLocale === 'en'
? savedLocale
: browserPrefersChinese()
? 'zh'
: 'en'
if (locale === 'zh') {
void router.go('/zh/')
}
},
}
+24 -31
View File
@@ -9,42 +9,28 @@ BitLogger is a structured logging library for MoonBit projects.
BitLogger gives you consistent levels, targets, structured fields, configurable text output, native file logging, and an async logging layer.
## Start With A Working Flow
The documentation is organized around complete usage flows. Start with an executable logger, then move into file output, configuration, async lifecycle, and extensions. The API reference remains the precise symbol-level reference.
### 1. Install
```bash
moon new log-demo
cd log-demo
moon add Nanaloveyuki/BitLogger@0.7.3
```
### 2. Import And Log
Add the package import to your application's `moon.pkg`:
## Quick Start
```moonbit
import {
"Nanaloveyuki/BitLogger/src" @log,
}
let logger = build_logger(
text_console(
min_level=Level::Info,
target="demo",
text_formatter=TextFormatterConfig::new(show_timestamp=false, separator=" | "),
),
)
logger.info("starting", fields=[field("port", "8080")])
ignore(logger.flush())
```
```moonbit
fn main {
let logger = @log.build_logger(
@log.console(min_level=@log.Level::Info, target="app"),
)
logger.info("server started", fields=[@log.field("port", "8080")])
}
```
Start with `console(...)`, `json_console(...)`, `text_console(...)`, or `file(...)`, then add `with_queue(...)` or `with_file_rotation(...)` only when needed.
Continue with the [Examples guide](./examples/index.md): console fields, file rotation, JSON configuration, and async lifecycle are each documented as a complete path.
Use `Logger::new(...)` when you want to assemble custom sink graphs directly.
## Support Status
- CI checks and tests `native`, `wasm`, `js`, and `wasm-gc` for the main `src` package and `src-async`
- Current local verification covers `native`, `js`, `wasm`, and `wasm-gc` for the main `src` package and `src-async`
- `llvm` is still treated as experimental in the current release context and was not locally re-verified in the current environment
- The source packages still declare `wasm` support alongside `native`, `llvm`, `js`, and `wasm-gc`; see [`target-verification.md`](./api/target-verification.md) for the current release-facing verification boundary
- File output is a native capability; check `native_files_supported()` in cross-target code
@@ -58,12 +44,19 @@ Continue with the [Examples guide](./examples/index.md): console fields, file ro
- Config-based builders: `build_logger(...)` and `build_async_logger(...)`
- Composition helpers: queue, filter, patch, fanout, split, callback
- Separate async package under `src-async`
- Trace-context binding through standard `trace_id`, `span_id`, `trace_flags`, and `trace_state` fields
## Examples
- `examples/console_basic/`: minimal console and JSON console example
- `examples/text_formatter/`: text formatting and template example
- `examples/style_tags/`: style tags and colored output example
- `examples/config_build/`: config-based build example
- `examples/presets/`: common preset combinations
- `examples/file_rotation/`: native file logging and rotation example
- `examples/async_basic/`: async logging example
## Documentation
- [Examples](./examples/index.md): complete application-facing usage flows
- [Extend](./extend/index.md): queueing, sink composition, formatting, and target boundaries
- [API index](./api/index.md): canonical API reference, organized as one public API per file
- [src package README](https://github.com/Nanaloveyuki/BitLogger/blob/main/src/README.mbt.md): package-level usage notes and target reminders
- [`docs/changes/`](./changes/): versioned release notes and publish-facing change summaries
@@ -13,14 +13,14 @@ key-word:
## Async-logger-build-config-to-json
Convert `AsyncLoggerBuildConfig` into a `Json`. This helper exports both the base synchronous logger config and the async runtime config as one structured payload.
Convert `AsyncLoggerBuildConfig` into a `JsonValue`. This helper exports both the base synchronous logger config and the async runtime config as one structured payload.
### Interface
```moonbit
pub fn async_logger_build_config_to_json(
config : AsyncLoggerBuildConfig,
) -> Json {}
) -> @json_parser.JsonValue {}
```
#### input
@@ -29,7 +29,7 @@ pub fn async_logger_build_config_to_json(
#### output
- `Json` - Structured JSON representation of the full async build config.
- `JsonValue` - Structured JSON representation of the full async build config.
### Explanation
+4 -5
View File
@@ -2,7 +2,7 @@
name: async-logger-close
group: api
category: async
update-time: 20260707
update-time: 20260614
description: Close the async logger queue immediately and optionally convert current pending backlog into dropped records before queue closure.
key-word:
- async
@@ -35,14 +35,13 @@ pub fn[S] AsyncLogger::close(self : AsyncLogger[S], clear? : Bool = false) -> Un
Detailed rules explaining key parameters and behaviors
- `close(...)` marks the logger as closed immediately.
- If a worker is still active when `close(...)` runs, the lifecycle phase moves into the closing path first and only settles into a terminal closed phase after worker exit.
- `clear=false` closes the queue without explicitly abandoning pending records in the helper itself.
- `clear=true` counts pending records as dropped and resets `pending_count` to `0` before closing the queue.
- This helper does not itself wait for the worker to finish.
- `close(...)` also does not change `has_failed()` or `last_error()`; it is a closure primitive, not a failure reset API.
- Because this is a low-level close primitive, it does not first run `wait_idle()` or apply the runtime-dependent fallback logic used by `shutdown()`.
- After closure, later log attempts are rejected in the shared async log path before record build, patch, or filter work starts.
- That means post-close late logs no longer add pending or dropped counts, and they no longer trigger patch/filter side effects on one backend but not another.
- After closure, later log attempts do not add new pending or dropped counts, but backend behavior can still differ before the closed queue rejects the record.
- In the current direct coverage, compatibility runtimes short-circuit before patch-path work on late log attempts, while native-worker runtimes may still build and patch the record before the closed queue rejects it.
### How to Use
@@ -73,7 +72,7 @@ e.g.:
- If `clear=false`, pending records may still exist after closure until worker drain or later cleanup resolves them.
- If callers perform late log attempts after closure, backlog counters still stay unchanged and patch/filter side effects stay skipped.
- If callers perform late log attempts after closure, backlog counters still stay unchanged, but patch-path side effects are runtime-dependent and should not be treated as a portable post-close contract.
- If callers need graceful waiting for drain completion, `shutdown()` is usually the better API.
+3 -3
View File
@@ -13,12 +13,12 @@ key-word:
## Async-logger-config-to-json
Convert a typed `AsyncLoggerConfig` into a `Json`. This helper exports async queue capacity, overflow policy, batch sizing, linger timing, and flush behavior in a structured form.
Convert a typed `AsyncLoggerConfig` into a `JsonValue`. This helper exports async queue capacity, overflow policy, batch sizing, linger timing, and flush behavior in a structured form.
### Interface
```moonbit
pub fn async_logger_config_to_json(config : AsyncLoggerConfig) -> Json {}
pub fn async_logger_config_to_json(config : AsyncLoggerConfig) -> @json_parser.JsonValue {}
```
#### input
@@ -27,7 +27,7 @@ pub fn async_logger_config_to_json(config : AsyncLoggerConfig) -> Json {}
#### output
- `Json` - Structured JSON representation of the async config.
- `JsonValue` - Structured JSON representation of the async config.
### Explanation
+4 -6
View File
@@ -2,8 +2,8 @@
name: async-logger-flush-policy
group: api
category: async
update-time: 20260707
description: Read the async logger flush policy currently governing batch-end and shutdown-end flush-callback timing.
update-time: 20260614
description: Read the async logger flush policy currently governing batch-end and shutdown-end flushing behavior.
key-word:
- async
- logger
@@ -37,10 +37,8 @@ Detailed rules explaining key parameters and behaviors
- `Batch` means the worker invokes the stored async flush callback after each completed drained batch, not after every individual record write.
- `Shutdown` means the worker invokes the stored async flush callback once after the worker loop exits.
- `Never` leaves that explicit callback path unused and relies entirely on sink behavior or external control.
- This helper reports callback timing policy, not a progress count contract.
- The callback is now treated as an attempted flush action with optional failure, not as a meaningful returned item count.
- Builder routes that wrap `RuntimeSink` align with the sync/runtime facade by calling `RuntimeSink::flush_progress()` inside that callback and discarding the returned progress details.
- Text-specific async builder paths still keep the default no-op flush callback even when the visible policy is `Batch` or `Shutdown`, so the reported policy can describe when the callback would run without implying extra sink work actually happens on that path.
- This helper reports callback timing policy, not a guarantee that a particular sink type has a meaningful built-in flush effect on every constructor path.
- In particular, text-specific async builder paths keep the default no-op flush callback even when the visible policy is `Batch` or `Shutdown`, so the reported policy can describe when the callback would run without implying extra sink work actually happens on that path.
### How to Use
+4 -4
View File
@@ -2,7 +2,7 @@
name: async-logger-has-failed
group: api
category: async
update-time: 20260707
update-time: 20260614
description: Read whether the async logger worker has recorded a runtime failure after run() startup reset and drain execution.
key-word:
- async
@@ -35,7 +35,7 @@ Detailed rules explaining key parameters and behaviors
- `run()` clears previous failure state at startup.
- `run()` also clears the stored `last_error()` string at startup before drain work begins.
- If the worker loop raises an error, the logger transitions its lifecycle phase to `failed` or `closed_failed` and exposes that failure through this flag.
- If the worker loop raises an error, the logger records that failure and exposes it through this flag.
- Once set by a failed run, the flag stays `true` until a later `run()` invocation actually starts and resets it.
- Failure-driven shutdown does not clear this flag by itself, so `has_failed()` can remain `true` even after the logger is already closed.
- This helper is intentionally compact and should usually be paired with `last_error()` for details.
@@ -71,9 +71,9 @@ e.g.:
- If `has_failed()` is `false`, queue pressure or dropped records may still exist for non-failure reasons.
- If `has_failed()` becomes `true`, `wait_idle()` may stop early while pending records still remain until a later close or clear path handles them.
- In the current regression coverage, that later handling can be an explicit `close(clear=true)` that resets pending backlog immediately or a `shutdown(...)` path that clears retained pending backlog into dropped records before returning.
- In the current regression coverage, that later handling can be an explicit `close(clear=true)` that resets pending backlog immediately or a runtime-dependent `shutdown(...)` path that either clears pending into dropped records or leaves the closed-queue remainder visible.
- If `has_failed()` is still `true` after shutdown, that does not by itself mean cleanup failed; the logger may already be `phase=closed_failed` and `terminal=true` while the retained failure record is still intentionally visible.
- If `has_failed()` is still `true` after shutdown, that does not by itself mean cleanup failed; the logger may already be `is_closed=true` while the remaining pending-versus-dropped outcome still reflects the active runtime's shutdown path.
- If `has_failed()` is `true`, callers should inspect `last_error()` or `state()` for more context.
+5 -5
View File
@@ -2,7 +2,7 @@
name: async-logger-is-closed
group: api
category: async
update-time: 20260707
update-time: 20260614
description: Read whether the async logger has entered closed lifecycle state and should no longer be treated as a normal active enqueue target.
key-word:
- async
@@ -36,11 +36,11 @@ Detailed rules explaining key parameters and behaviors
- `close(...)` sets the closed state immediately.
- `shutdown(...)` also results in a closed logger by the end of its lifecycle flow.
- A closed logger should no longer be treated as a normal active enqueue target.
- This helper is derived from the current lifecycle phase rather than from an independent closed flag ref.
- This helper is only a direct read of the current `is_closed` ref; it does not wait for drain completion or clear any other state.
- This helper reflects lifecycle state only and does not indicate whether the worker is still draining.
- `is_closed()` becoming `true` does not imply the logger reached a clean success state. Failure flags, retained `last_error()`, and remaining backlog-related counters can still reflect the earlier worker outcome.
- After shutdown on a worker-failure path, `is_closed()` can therefore be `true` while retained failure state still remains visible under `phase=closed_failed`.
- Late log attempts are rejected in the shared async log path after closure, so `is_closed()` now aligns with a stable post-close enqueue rejection contract.
- After shutdown on a worker-failure path, `is_closed()` can therefore be `true` while backlog cleanup remains runtime-dependent: native-worker runtimes can convert leftover pending records into dropped ones, while compatibility runtimes can still report the remaining queue entries as pending.
- Exact post-close logging behavior is runtime-dependent: compatibility runtimes can short-circuit before patch and enqueue work, while native-worker runtimes may still build and patch a record before the closed queue rejects it, so `is_closed()` should be read as a lifecycle signal rather than a full enqueue-policy contract.
### How to Use
@@ -74,7 +74,7 @@ e.g.:
- If callers need to know whether the worker is still active, they should also inspect `is_running()`.
- If callers need to know whether the logger is also terminal or rerunnable, they should inspect `state().terminal` or `state().can_rerun`.
- If callers need to know whether closure also prevented later log attempts on the current backend, they must interpret this together with the active runtime behavior rather than this flag alone.
- Closing a logger does not by itself reset `has_failed()` or `last_error()`.
+4 -4
View File
@@ -2,7 +2,7 @@
name: async-logger-is-running
group: api
category: async
update-time: 20260707
update-time: 20260614
description: Read whether the async logger worker loop is currently running, regardless of queue backlog or recorded failure state.
key-word:
- async
@@ -36,8 +36,8 @@ Detailed rules explaining key parameters and behaviors
- `run()` sets the running state while the worker loop is active.
- The flag is cleared when the worker exits normally or after failure handling finishes.
- A logger may be closed while still running briefly during final drain or shutdown processing.
- After a worker failure, the logger can already be `is_running=false` while still retaining `has_failed=true`, the recorded `last_error()`, and leftover dropped-count cleanup.
- This helper is derived from the current lifecycle phase rather than from an independent running flag ref; it does not wait, synchronize, or infer why the value is what it is.
- After a worker failure, the logger can already be `is_running=false` while still retaining `has_failed=true`, the recorded `last_error()`, and runtime-dependent leftover backlog or dropped-count cleanup.
- This helper is only a direct read of the current `is_running` ref; it does not wait, synchronize, or infer why the value is what it is.
- This helper focuses on worker activity rather than queue size or failure details.
- `is_running()` can be `false` even when `pending_count()` is still nonzero, for example if the worker was never started or if it exited after a recorded failure.
- A later `run()` attempt can flip `is_running()` back to `true` before that retained failure/backlog state has been fully drained, because the restarted worker clears stale failure state only once the new run has actually started.
@@ -71,7 +71,7 @@ In this example, callers watch the worker lifecycle directly.
e.g.:
- If `is_running()` is `false`, pending records may still exist if the worker was never started or has already failed.
- If `is_running()` is `false`, the logger may also already be closed while still retaining the previous failure record and the cleanup result from shutdown.
- If `is_running()` is `false`, the logger may also already be closed while still retaining the previous failure record and a runtime-dependent pending-versus-dropped cleanup result from shutdown.
- If callers need a one-shot lifecycle flow, `shutdown()` is usually better than manual polling.
+2 -2
View File
@@ -2,7 +2,7 @@
name: async-logger-last-error
group: api
category: async
update-time: 20260707
update-time: 20260614
description: Read the last error string recorded by the async logger worker after run() resets and runtime failure capture.
key-word:
- async
@@ -76,7 +76,7 @@ e.g.:
- `close()` or `shutdown()` do not clear a previously recorded error string by themselves; the reset happens only after a later `run()` has already started.
- If the same error string is still present after shutdown, that does not by itself mean cleanup was skipped; the logger may already be `phase=closed_failed` and `terminal=true` while the retained failure record is still intentionally visible.
- If the same error string is still present after shutdown, that does not by itself mean cleanup was skipped; the logger may already be `is_closed=true` while the remaining pending-versus-dropped outcome still reflects the active runtime's shutdown path.
### Notes
+6 -10
View File
@@ -2,7 +2,7 @@
name: async-logger-run
group: api
category: async
update-time: 20260707
update-time: 20260614
description: Start the async logger worker loop so queued records are drained to the underlying sink while lifecycle and failure state are reset and updated around execution.
key-word:
- async
@@ -34,15 +34,13 @@ pub async fn[S : @bitlogger.Sink] AsyncLogger::run(self : AsyncLogger[S]) -> Uni
Detailed rules explaining key parameters and behaviors
- `run()` sets `is_running` to `true` before worker execution begins.
- `run()` moves the logger lifecycle phase from `ready` or `failed` into `running`.
- `run()` now enforces a single-worker contract. If the same logger already has a running worker, the later call raises `AsyncLoggerAlreadyRunning` instead of silently starting another drain loop.
- If the logger is already closed, `run()` raises `AsyncLoggerClosed` instead of trying to restart a terminal logger.
- Every invocation clears previous failure state first by setting `has_failed=false` and `last_error()` to an empty string once that `run()` call has actually started executing.
- The method then keeps draining records until `queue.get()` stops with `AsyncLoggerClosed` or a worker error escapes.
- On a normal queue-close exit, `run()` leaves the logger in `closed` if shutdown/close had already started, otherwise it returns to `ready`.
- On failure, the logger records `last_error`, transitions to `failed` or `closed_failed`, and then raises the error back out of `run()`.
- On a normal queue-close exit, `run()` clears `is_running` and returns normally.
- On failure, the logger records `has_failed=true`, stores the error text in `last_error`, clears `is_running`, and then raises the error back out of `run()`.
- A worker failure does not guarantee the async backlog was fully drained first. If the failure happens after some records were already written, later queued records can remain pending when `run()` exits.
- A later `run()` invocation can resume draining that retained backlog, but the stale failure flag and stale `last_error()` value are only cleared after the new worker call actually begins running.
- This helper does not enforce a single-worker guard by itself, so the public contract should be treated as application-controlled worker startup rather than an API that deduplicates repeated `run()` calls.
### How to Use
@@ -82,9 +80,7 @@ e.g.:
- A later `run()` attempt starts from a fresh failure flag and empty `last_error()` string once that retrying worker has actually started, even if an earlier run failed.
- Starting more than one `run()` task for the same logger raises `AsyncLoggerAlreadyRunning` on the later attempt.
- Starting `run()` after a terminal close path raises `AsyncLoggerClosed`.
- Starting more than one `run()` task for the same logger is not prevented by this method and can produce application-level worker coordination bugs.
### Notes
@@ -94,4 +90,4 @@ e.g.:
3. Pair it with `has_failed()`, `last_error()`, or `state()` when tests need to inspect how a worker exit affected logger health.
4. Start one deliberate worker task per logger. A concurrent second startup now fails explicitly with `AsyncLoggerAlreadyRunning`.
4. Start one deliberate worker task per logger unless your own code is intentionally coordinating a different pattern.
+14 -7
View File
@@ -2,8 +2,8 @@
name: async-logger-shutdown
group: api
category: async
update-time: 20260707
description: Gracefully stop an async logger by waiting for idle or clearing queued work, then waiting for any active worker to finish.
update-time: 20260614
description: Gracefully stop an async logger by waiting for idle or clearing queued work, with worker-wait behavior depending on the active async runtime.
key-word:
- async
- logger
@@ -35,10 +35,12 @@ pub async fn[S] AsyncLogger::shutdown(self : AsyncLogger[S], clear? : Bool = fal
Detailed rules explaining key parameters and behaviors
- `clear=false` first waits for idle, then closes the logger.
- If `wait_idle()` returned early because a worker failure left backlog behind, shutdown now converts that retained pending backlog into dropped records with `close(clear=true)` before returning.
- In runtimes where shutdown clearing after idle is enabled, remaining backlog after `wait_idle()` triggers a fallback `close(clear=true)`.
- `clear=true` immediately closes and abandons pending records, even if no worker was ever started for that logger.
- After either shutdown branch starts closing, the helper waits until `is_running()` becomes `false` before returning.
- In lifecycle-phase terms, shutdown drives the logger into `closing` while a worker is still active, then settles into `closed` or `closed_failed` once that worker has exited.
- In runtimes where shutdown waits for workers, the method then waits until `is_running()` becomes `false` before returning.
- In the current backend split, native-worker runtimes enable both the post-`wait_idle()` clear fallback and the final wait-for-worker phase, while compatibility runtimes skip both extra steps.
- That means a failure-short-circuited `wait_idle()` can still be followed by forced pending-to-dropped cleanup on native-worker runtimes, while compatibility runtimes close without that extra forced clear step.
- In the current tested failure path, native-worker shutdown turns the leftover pending item into one more dropped record, while compatibility shutdown leaves that leftover closed-queue count in `pending_count()` instead.
- Shutdown itself does not clear retained worker failure state. If a previous `run()` already recorded `has_failed=true` and a non-empty `last_error()`, those diagnostics can remain visible after shutdown completes.
- Because `clear=false` delegates to `wait_idle()` first, shutdown can also wait indefinitely when pending records exist but no worker is making progress and no failure flag is raised.
@@ -69,10 +71,15 @@ In this example, pending work is abandoned intentionally so shutdown can complet
e.g.:
- If `clear=true`, pending records are intentionally dropped rather than drained.
- If `wait_idle()` returns early because the worker failed, shutdown still finishes by converting retained pending backlog into dropped records before it returns.
- If `wait_idle()` returns early because the worker failed, shutdown behavior after that point still depends on the active runtime's fallback and worker-wait rules.
- After a worker failure, native-worker shutdown may convert the remaining backlog into dropped records, while compatibility shutdown can leave the pending counter reflecting that leftover closed queue state.
- In the current direct regression coverage, that split appears as `pending_count() == 0` and `dropped_count()` increasing on native-worker runtimes, versus `pending_count() > 0` and no extra dropped cleanup on compatibility runtimes.
- Even after shutdown finishes with `is_closed=true`, callers can still observe retained `has_failed()` and `last_error()` from an earlier worker failure.
- In compatibility-style runtimes without background-worker waiting, shutdown still closes the logger but may not perform the extra wait-for-worker phase described for native-worker runtimes.
- If pending work exists but no worker was started, `shutdown(clear=false)` may never reach its later close step because it is still waiting inside `wait_idle()`.
- If callers skip `shutdown()` and only inspect flags manually, it is easier to leave the worker lifecycle in an unclear state.
@@ -81,7 +88,7 @@ e.g.:
1. Prefer this API over raw `close()` in normal application shutdown paths.
2. `shutdown()` now always waits for an already-running worker to leave `is_running=true` before returning.
2. Exact post-close waiting behavior depends on the active async runtime mode.
3. Choose `clear=true` only when loss of queued records is acceptable.
+16 -9
View File
@@ -2,8 +2,8 @@
name: async-logger-state-new
group: api
category: async
update-time: 20260707
description: Construct an AsyncLoggerState snapshot from explicit runtime, lifecycle phase, queue, failure text, and flush-policy values without probing a live logger.
update-time: 20260614
description: Construct an AsyncLoggerState snapshot from explicit runtime, queue, lifecycle, failure, and flush-policy values without probing a live logger.
key-word:
- async
- logger
@@ -20,9 +20,11 @@ Construct an `AsyncLoggerState` snapshot from explicit runtime, queue, lifecycle
```moonbit
pub fn AsyncLoggerState::new(
runtime : AsyncRuntimeState,
phase : AsyncLifecyclePhase,
pending_count : Int,
dropped_count : Int,
is_closed : Bool,
is_running : Bool,
has_failed : Bool,
last_error : String,
flush_policy : AsyncFlushPolicy,
) -> AsyncLoggerState {
@@ -31,9 +33,11 @@ pub fn AsyncLoggerState::new(
#### input
- `runtime : AsyncRuntimeState` - Embedded backend-level runtime snapshot.
- `phase : AsyncLifecyclePhase` - Primary lifecycle conclusion for the snapshot.
- `pending_count : Int` - Current async queue backlog.
- `dropped_count : Int` - Current dropped-record count.
- `is_closed : Bool` - Whether the logger has been closed.
- `is_running : Bool` - Whether the logger worker loop is currently running.
- `has_failed : Bool` - Whether the logger has recorded a runtime failure state.
- `last_error : String` - Latest error text, or an empty string when no failure has been recorded.
- `flush_policy : AsyncFlushPolicy` - Active async flush policy for the logger.
@@ -45,12 +49,11 @@ pub fn AsyncLoggerState::new(
Detailed rules explaining key parameters and behaviors
- This constructor packages the supplied runtime, phase, counters, last error, and flush policy into one public snapshot value.
- This constructor simply packages the supplied fields into one public snapshot value.
- It does not inspect a live logger instance by itself.
- `AsyncLogger::state()` is the higher-level API that reads these values from a concrete logger.
- It also does not validate whether the supplied fields represent a combination that could come from one real logger instant.
- The supplied `runtime : AsyncRuntimeState` is stored exactly as provided; this constructor does not recompute `mode` or `background_worker` from the active backend.
- The constructor derives `is_closed`, `is_running`, `has_failed`, `backlog_retained`, `can_rerun`, and `terminal` from the supplied `phase` and `pending_count`.
- The constructed value matches the same public shape used by async logger serializers.
- Because `AsyncLoggerState` is only a data snapshot type, this constructor is mainly useful for tests, adapters, and synthetic diagnostics rather than ordinary logger inspection.
- Serialization helpers accept any `AsyncLoggerState` value, including hand-built ones from this constructor.
@@ -66,9 +69,11 @@ When tests or adapters should construct a full async logger state explicitly:
```moonbit
let state = AsyncLoggerState::new(
runtime=AsyncRuntimeState::new(AsyncRuntimeMode::Compatibility, false),
phase=AsyncLifecyclePhase::Running,
pending_count=0,
dropped_count=0,
is_closed=false,
is_running=true,
has_failed=false,
last_error="",
flush_policy=AsyncFlushPolicy::Never,
)
@@ -82,9 +87,11 @@ When code should prepare a typed logger state value for later export:
```moonbit
let state = AsyncLoggerState::new(
runtime=async_runtime_state(),
phase=logger.phase(),
pending_count=logger.pending_count(),
dropped_count=logger.dropped_count(),
is_closed=logger.is_closed(),
is_running=logger.is_running(),
has_failed=logger.has_failed(),
last_error=logger.last_error(),
flush_policy=logger.flush_policy(),
)
@@ -103,7 +110,7 @@ e.g.:
- If callers want the current backend-derived runtime pair instead of a synthetic one, they must pass `async_runtime_state()` explicitly or use `AsyncLogger::state()`.
- This constructor does not apply cleanup semantics such as clearing `last_error` on restart or draining pending records; callers must provide the phase and counters exactly as they want them represented.
- This constructor does not apply cleanup semantics such as clearing `last_error` on restart or draining pending records; callers must provide those fields exactly as they want them represented.
### Notes
+8 -8
View File
@@ -2,7 +2,7 @@
name: async-logger-state-to-json
group: api
category: async
update-time: 20260707
update-time: 20260614
description: Convert an AsyncLoggerState snapshot into a JSON value for diagnostics and transport using the canonical nested runtime shape and flush-policy labels.
key-word:
- async
@@ -13,12 +13,12 @@ key-word:
## Async-logger-state-to-json
Convert `AsyncLoggerState` into a `Json`. This helper is the structured export path for async logger runtime snapshots or manually constructed state values when callers want machine-readable diagnostics instead of a plain string.
Convert `AsyncLoggerState` into a `JsonValue`. This helper is the structured export path for async logger runtime snapshots or manually constructed state values when callers want machine-readable diagnostics instead of a plain string.
### Interface
```moonbit
pub fn async_logger_state_to_json(state : AsyncLoggerState) -> Json {}
pub fn async_logger_state_to_json(state : AsyncLoggerState) -> @json_parser.JsonValue {}
```
#### input
@@ -27,20 +27,20 @@ pub fn async_logger_state_to_json(state : AsyncLoggerState) -> Json {}
#### output
- `Json` - Structured JSON representation of the async logger snapshot.
- `JsonValue` - Structured JSON representation of the async logger snapshot.
### Explanation
Detailed rules explaining key parameters and behaviors
- The JSON includes runtime mode, lifecycle phase, derived lifecycle conclusions, queue counters, last error, and flush policy.
- The top-level fields are `runtime`, `phase`, `pending_count`, `dropped_count`, `is_closed`, `is_running`, `has_failed`, `backlog_retained`, `can_rerun`, `terminal`, `last_error`, and `flush_policy`.
- The JSON includes runtime mode, worker support, queue counters, lifecycle flags, last error, and flush policy.
- The top-level fields are `runtime`, `pending_count`, `dropped_count`, `is_closed`, `is_running`, `has_failed`, `last_error`, and `flush_policy`.
- The nested `runtime` field reuses `async_runtime_state_to_json(...)`, and `flush_policy` is serialized with the canonical labels `Never`, `Batch`, or `Shutdown`.
- The public helper returns the same internal JSON snapshot shape used by `stringify_async_logger_state(...)`, so both export paths stay aligned without duplicate field assembly logic.
- This helper is suitable for health endpoints, diagnostics payloads, and custom serialization flows.
- It shares the same stable field names used by `stringify_async_logger_state(...)`.
- The state must already have been captured or constructed before serialization.
- Serialization preserves whatever snapshot combination it receives, including lifecycle phase and failure/backlog combinations together with remaining backlog counts.
- Serialization preserves whatever snapshot combination it receives, including failure flags together with remaining backlog counts.
- This helper never rereads a logger instance by itself. If callers pass an older or manually constructed `AsyncLoggerState`, the JSON reflects that provided value exactly rather than refreshing fields from live runtime state.
- It also does not normalize mixed diagnostic combinations. If the provided snapshot says `is_closed=true` together with retained `has_failed=true`, `last_error`, or non-zero backlog counters, those exact combinations are emitted unchanged.
@@ -62,7 +62,7 @@ In this example, callers receive a structured value that can be composed into la
When another serializer or pipeline expects a JSON value:
```moonbit
let payload = async_logger_state_to_json(logger.state())
println(payload.stringify())
println(@json_parser.stringify(payload))
```
In this example, the helper stays useful even outside the built-in stringify wrapper.
+6 -7
View File
@@ -2,8 +2,8 @@
name: async-logger-state-type
group: api
category: async
update-time: 20260707
description: Public async logger state alias used for queue, lifecycle phase, derived lifecycle conclusions, runtime, and flush-policy diagnostics.
update-time: 20260614
description: Public async logger state alias used for queue, lifecycle, runtime, and flush-policy diagnostics.
key-word:
- async
- logger
@@ -23,7 +23,7 @@ pub type AsyncLoggerState = @utils.AsyncLoggerState
#### output
- `AsyncLoggerState` - Public async logger snapshot containing `runtime`, `phase`, queue counters, derived lifecycle conclusions, `last_error`, and `flush_policy`.
- `AsyncLoggerState` - Public async logger snapshot containing `runtime`, `pending_count`, `dropped_count`, `is_closed`, `is_running`, `has_failed`, `last_error`, and `flush_policy`.
### Explanation
@@ -31,14 +31,13 @@ Detailed rules explaining key parameters and behaviors
- This is a type alias, not a live logger handle.
- The `runtime` field embeds an `AsyncRuntimeState` snapshot.
- The remaining fields capture queue counts, lifecycle phase, derived lifecycle conclusions, failure state, last error text, and active flush policy.
- The remaining fields capture queue counts, lifecycle status, failure state, last error text, and active flush policy.
- `AsyncLogger::state()` returns this type directly, while `async_logger_state_to_json(...)` and `stringify_async_logger_state(...)` export the same data shape for diagnostics.
- `AsyncLogger::state()` currently builds this snapshot from `async_runtime_state()` plus the logger's current counters, lifecycle phase, last error, and flush policy.
- `AsyncLogger::state()` currently builds this snapshot from `async_runtime_state()` plus the logger's current counters, lifecycle flags, last error, and flush policy.
- When the value comes from `AsyncLogger::state()`, the fields are read one by one rather than through a transactional snapshot primitive.
- `AsyncLoggerState::new(...)` can also construct this type manually, but manual construction is synthetic snapshot data and does not read one live logger instant by itself.
- The type itself does not distinguish live logger snapshots from hand-built ones; callers must track whether a given `AsyncLoggerState` value came from `AsyncLogger::state()` or from manual construction.
- `phase` is the strongest lifecycle conclusion in the snapshot, while `is_closed`, `is_running`, `has_failed`, `backlog_retained`, `can_rerun`, and `terminal` are the main derived convenience reads.
- When a live snapshot is taken after worker failure, `phase=failed`, a retained `last_error`, `backlog_retained=true`, and non-zero `pending_count` may legitimately coexist until later cleanup or restart.
- When a live snapshot is taken after worker failure, `has_failed=true`, a retained `last_error`, and non-zero `pending_count` may legitimately coexist until later cleanup or restart.
### How to Use
+9 -13
View File
@@ -2,8 +2,8 @@
name: async-logger-state
group: api
category: async
update-time: 20260707
description: Read a full async logger runtime snapshot including runtime, lifecycle phase, derived lifecycle conclusions, queue counters, last error, and flush policy.
update-time: 20260614
description: Read a full async logger runtime snapshot including the embedded runtime snapshot, queue counters, lifecycle flags, last error, and flush policy.
key-word:
- async
- state
@@ -27,26 +27,22 @@ pub fn[S] AsyncLogger::state(self : AsyncLogger[S]) -> AsyncLoggerState {}
#### output
- `AsyncLoggerState` - A snapshot containing runtime mode, lifecycle phase, derived lifecycle conclusions, queue counts, last error, and flush policy.
- `AsyncLoggerState` - A snapshot containing runtime mode, worker support, queue counts, lifecycle flags, last error, and flush policy.
### Explanation
Detailed rules explaining key parameters and behaviors
- `AsyncLoggerState` includes `runtime`, `phase`, `pending_count`, `dropped_count`, `is_closed`, `is_running`, `has_failed`, `backlog_retained`, `can_rerun`, `terminal`, `last_error`, and `flush_policy`.
- `AsyncLoggerState` includes `runtime`, `pending_count`, `dropped_count`, `is_closed`, `is_running`, `has_failed`, `last_error`, and `flush_policy`.
- `state()` returns a value snapshot rather than a live handle.
- This helper is equivalent to `AsyncLoggerState::new(async_runtime_state(), self.phase(), self.pending_count(), self.dropped_count(), self.last_error(), self.flush_policy())`.
- This helper is equivalent to `AsyncLoggerState::new(async_runtime_state(), self.pending_count(), self.dropped_count(), self.is_closed(), self.is_running(), self.has_failed(), self.last_error(), self.flush_policy())`.
- `async_logger_state_to_json(...)` and `stringify_async_logger_state(...)` convert the snapshot to stable diagnostic output.
- `runtime` embeds the result of `async_runtime_state()` from the moment `state()` is called, so callers do not need to join separate helpers manually.
- The runtime portion is therefore recomputed from the active backend helper on each call, while the remaining fields come from the logger's current counters, lifecycle phase, derived lifecycle conclusions, and flush policy at that same general moment.
- The runtime portion is therefore recomputed from the active backend helper on each call, while the remaining fields come from the logger's current counters, flags, and flush policy at that same general moment.
- Because the snapshot is assembled field by field when `state()` is called, later logger changes require calling `state()` again rather than reusing an older `AsyncLoggerState` value as if it refreshed itself.
- That field-by-field assembly also means this helper is not an atomic freeze across all refs; under concurrent logger activity, neighboring fields can reflect slightly different instants.
- `phase` is the primary lifecycle conclusion. The current public phases are `ready`, `running`, `failed`, `closing`, `closed`, and `closed_failed`.
- `backlog_retained=true` means pending backlog still exists while the logger is no longer actively draining it.
- `can_rerun=true` means the current phase still allows a future `run()` call to restart drain work.
- `terminal=true` means the logger is closed, no worker is active, and no pending backlog remains.
- After a worker failure, snapshots can legitimately report `phase=failed`, `has_failed=true`, `backlog_retained=true`, a non-empty `last_error`, and `pending_count>0` together until later cleanup or restart changes them.
- After shutdown cleanup on an already failed logger, snapshots can also legitimately report `phase=closed_failed`, `is_closed=true`, `terminal=true`, retained `has_failed=true`, and the same `last_error()`.
- After a worker failure, `has_failed=true`, a non-empty `last_error`, and `pending_count>0` can legitimately appear together in one snapshot until later cleanup or a later started `run()` changes them.
- After shutdown cleanup on an already failed logger, snapshots can also legitimately show `is_closed=true` together with retained `has_failed=true` and the same `last_error()`, while `pending_count` versus `dropped_count` still reflects the active runtime's cleanup path.
- `state()` only reports the current field values; it does not clear failure state, drain backlog, or synchronize pending work by itself.
### How to Use
@@ -94,7 +90,7 @@ e.g.:
- A snapshot showing `has_failed=true` does not imply `pending_count` is already `0`; remaining queued records may still be visible until later cleanup or restart.
- A snapshot showing `is_closed=true` also does not imply failure state was cleared; after failure-driven shutdown, `phase=closed_failed`, `has_failed=true`, and the recorded `last_error` can still remain visible until a later `run()` actually restarts the logger.
- A snapshot showing `is_closed=true` also does not imply failure state was cleared; after failure-driven shutdown, `has_failed=true` and the recorded `last_error` can still remain visible until a later `run()` actually restarts the logger.
### Notes
@@ -2,7 +2,7 @@
name: async-logger-to-library-async-logger
group: api
category: facade
update-time: 20260707
update-time: 20260614
description: Convert a full async logger into the narrower library-facing async facade without rebuilding or detaching the underlying async state.
key-word:
- async
@@ -38,8 +38,8 @@ Detailed rules explaining key parameters and behaviors
- The original `AsyncLogger[S]` handle remains the same live logger. If caller code keeps that original value, later facade calls and later unwraps still observe the same shared queue, counters, sink helpers, and lifecycle mutations.
- The returned facade keeps library-facing async operations including `log(...)`, `run()`, and `shutdown(...)`.
- Async inspection helpers and broader composition APIs remain on the underlying `AsyncLogger[S]` and are intentionally hidden until `to_async_logger()` is used again.
- If later facade-level `run()` or `shutdown()` calls record worker failure or perform shutdown cleanup, unwrapping later still exposes that same post-call state instead of a translated facade copy.
- That includes states where delegated shutdown already finished with `is_closed=true` while retained `has_failed()` and `last_error()` remain on the wrapped logger, together with the same retained dropped-count cleanup outcome.
- If later facade-level `run()` or `shutdown()` calls record worker failure, leave backlog behind, or follow runtime-dependent shutdown cleanup rules, unwrapping later still exposes that same post-call state instead of a translated facade copy.
- That includes states where delegated shutdown already finished with `is_closed=true` while retained `has_failed()` and `last_error()` remain on the wrapped logger, together with the same runtime-dependent pending-versus-dropped cleanup outcome.
- When `S` itself exposes richer runtime helpers, projecting to the library facade does not strip those capabilities from the wrapped logger; they are still reachable after `to_async_logger()`.
- When `S` is `RuntimeSink`, projection also preserves queued runtime state and file-backed runtime helper behavior behind the facade instead of replacing them with a library-specific copy.
- Unwrapping later with `to_async_logger()` therefore exposes the same queue counters, failure snapshots, file state, and runtime file controls that the original async logger already carried.
@@ -83,7 +83,7 @@ e.g.:
- Projection does not normalize failure snapshots; a later unwrap can still show combinations such as retained `last_error()` with remaining `pending_count()` when the wrapped async logger really ended up in that state.
- Projection also does not normalize delegated shutdown results; a later unwrap can still show `is_closed=true` together with retained `has_failed()`, the same `last_error()`, and the same retained dropped-count cleanup that accumulated behind the facade.
- Projection also does not normalize delegated shutdown results; a later unwrap can still show `is_closed=true` together with retained `has_failed()`, the same `last_error()`, and the same runtime-dependent leftover backlog or dropped-count cleanup that accumulated behind the facade.
- Projection also does not normalize richer runtime sink state; if the original async logger already carried queued runtime data or file-backed helper state, a later unwrap still exposes that same live state.
+10 -9
View File
@@ -2,7 +2,7 @@
name: async-logger-type
group: api
category: async
update-time: 20260707
update-time: 20260614
description: Public asynchronous logger root type used for queue-backed sink-preserving logging pipelines with explicit lifecycle, failure, and flush-callback state.
key-word:
- async
@@ -13,7 +13,7 @@ key-word:
## Async-logger-type
`AsyncLogger[S]` is the public asynchronous root logger type. It stores a concrete sink type `S` together with queue policy, runtime state counters, and lifecycle state, then serves as the base value for async composition, worker control, and async write APIs.
`AsyncLogger[S]` is the public asynchronous root logger type. It stores a concrete sink type `S` together with queue policy, runtime state counters, and lifecycle flags, then serves as the base value for async composition, worker control, and async write APIs.
### Interface
@@ -27,14 +27,16 @@ pub struct AsyncLogger[S] {
linger_ms : Int
flush_policy : AsyncFlushPolicy
sink : S
flush_callback : (S) -> Unit raise
flush_sink : (S) -> Int raise
context_fields : Array[@bitlogger.Field]
filter : (@bitlogger.Record) -> Bool
patch : @bitlogger.RecordPatch
queue : @async.Queue[@bitlogger.Record]
pending_count : Ref[Int]
dropped_count : Ref[Int]
phase : Ref[AsyncLifecyclePhase]
is_closed : Ref[Bool]
is_running : Ref[Bool]
has_failed : Ref[Bool]
last_error : Ref[String]
}
```
@@ -48,10 +50,9 @@ pub struct AsyncLogger[S] {
Detailed rules explaining key parameters and behaviors
- This is a public root struct, not a type alias.
- The current fields cover targeting, overflow policy, batching, linger timing, flush policy, the wrapped sink, context/filter/patch behavior, queue state, and the internal lifecycle phase model.
- `flush_callback : (S) -> Unit raise` stores the raising flush callback used by batch and shutdown flush policies.
- `pending_count`, `dropped_count`, `phase`, and `last_error` are the mutable runtime refs that power the higher-level lifecycle and diagnostics helpers.
- `phase` is the stronger internal lifecycle source of truth; helper reads such as `is_closed()`, `is_running()`, `has_failed()`, and the richer `state()` snapshot are derived from it.
- The current fields cover targeting, overflow policy, batching, linger timing, flush policy, the wrapped sink, context/filter/patch behavior, queue state, and worker lifecycle flags.
- `flush_sink : (S) -> Int raise` stores the raising flush callback used by batch and shutdown flush policies.
- `pending_count`, `dropped_count`, `is_closed`, `is_running`, `has_failed`, and `last_error` are mutable runtime refs that power the higher-level lifecycle and diagnostics helpers.
- The sink type parameter is preserved across async composition, which is why helpers such as `with_target(...)`, `with_context_fields(...)`, `with_filter(...)`, and `with_patch(...)` keep returning `AsyncLogger[S]`.
- `async_logger(...)` constructs this type as the main asynchronous entry point.
- This root type is also what sits underneath both async facade families: `ApplicationAsyncLogger` is a direct alias over the runtime-sink line, while `LibraryAsyncLogger[S]` is a narrowing wrapper around an `AsyncLogger[S]` value.
@@ -87,7 +88,7 @@ e.g.:
- Actual enqueue, worker, and flush behavior still depends on the wrapped sink `S`, async runtime support, and the configured queue policy.
- Post-close logging behavior now follows the shared close contract rather than backend-specific divergence, but lifecycle interpretation should still prefer `state()` over manual field reasoning.
- Post-close logging behavior is not a property of the struct shape alone; it also depends on the active runtime implementation.
### Notes
+2 -3
View File
@@ -2,7 +2,7 @@
name: async-logger-wait-idle
group: api
category: async
update-time: 20260707
update-time: 20260614
description: Wait until the async logger backlog drains to zero or a worker failure interrupts normal progress, using the repo's direct async call style.
key-word:
- async
@@ -37,7 +37,6 @@ Detailed rules explaining key parameters and behaviors
- If `has_failed()` becomes `true`, waiting stops early instead of continuing to spin.
- This API does not close the logger or stop the worker.
- A return from `wait_idle()` therefore means either backlog reached `0` or failure interrupted normal drain progress.
- In the stronger lifecycle model, the common post-failure interpretation is `phase=failed` together with `backlog_retained=true` while `pending_count() > 0` remains visible.
- `wait_idle()` does not clear retained failure state by itself, so if pending records remain after a worker failure, later `wait_idle()` calls also short-circuit until another path changes that state.
- A later `run()` can make `wait_idle()` meaningful again for the retained backlog, but only after that new worker invocation has actually started and reset the stale failure flag.
- If no worker is draining the queue and no failure flag is raised, `wait_idle()` can wait indefinitely.
@@ -74,7 +73,7 @@ e.g.:
- If the worker was never started, or if nothing is making pending records decrease, `wait_idle()` can block indefinitely.
- If callers need backlog cleanup after a failure-short-circuit, they still need a later `close(clear=true)` or `shutdown(...)` path.
- In the current direct coverage, `wait_idle()` can return with `pending_count() > 0` after a worker failure, and a later `shutdown(...)` call will convert that retained backlog into dropped records before returning.
- In the current direct coverage, `wait_idle()` can return with `pending_count() > 0` after a worker failure, and the later cleanup path may either clear that backlog explicitly or follow the runtime-dependent shutdown split documented on `shutdown(...)`.
- If callers retry `wait_idle()` immediately after such a failure without restarting the worker or forcing cleanup first, the call can return again with the same retained pending backlog.
@@ -1,21 +0,0 @@
---
name: async-logger-with-trace-context
group: api
category: async
update-time: 20260719
description: Bind TraceContext fields before records enter an AsyncLogger queue.
key-word:
- async
- trace
- context
---
## Async-logger-with-trace-context
```moonbit
let contextual = logger.with_trace_context(
@bitlogger.trace_context("trace-1", "span-1"),
)
```
The helper stores the mapped fields on the returned async logger and preserves its queue, lifecycle, target, and threshold state. Context is added before records are enqueued.
+5 -11
View File
@@ -2,7 +2,7 @@
name: async-logger
group: api
category: async
update-time: 20260707
update-time: 20260614
description: Create an async logger with bounded queueing, overflow policy, lifecycle helpers, background run control, and a raising flush callback.
key-word:
- async
@@ -23,7 +23,7 @@ pub fn[S] async_logger(
config~ : AsyncLoggerConfig = AsyncLoggerConfig::new(),
min_level~ : @bitlogger.Level = @bitlogger.Level::Info,
target~ : String = "",
flush~ : (S) -> Unit raise = fn(_) { () },
flush~ : (S) -> Int raise = fn(_) { 0 },
) -> AsyncLogger[S] {}
```
@@ -33,7 +33,7 @@ pub fn[S] async_logger(
- `config : AsyncLoggerConfig` - Queue size, overflow behavior, batching, linger, and flush policy.
- `min_level : Level` - Level gate applied before enqueue.
- `target : String` - Default target for emitted records.
- `flush : (S) -> Unit raise` - Flush callback used by batch/shutdown flush policies and allowed to raise if sink flushing fails.
- `flush : (S) -> Int raise` - Flush callback used by batch/shutdown flush policies and allowed to raise if sink flushing fails.
#### output
@@ -45,7 +45,7 @@ Detailed rules explaining key parameters and behaviors
- `async_logger(...)` only builds the logger. Actual background draining is started by `run()`.
- `async_logger(...)` returns the full `AsyncLogger[S]` surface directly. It is therefore the underlying constructor used by both application-facing async aliases and the narrower `LibraryAsyncLogger[S]` wrapper line.
- The constructed logger starts in lifecycle phase `ready`, with `last_error=""` and zeroed pending/dropped counters.
- The constructed logger starts with `is_closed=false`, `is_running=false`, `has_failed=false`, `last_error=""`, and zeroed pending/dropped counters.
- The constructed logger also keeps the core async target contract unchanged: `log(..., target=...)` can override the target for one call, while fixed-level helpers such as `info(...)`, `warn(...)`, and `error(...)` continue using the stored logger target unless code derives another logger first with `with_target(...)` or `child(...)`.
- Unlike synchronous `Logger`, async `with_context_fields(...)` and `bind(...)` preserve the visible `AsyncLogger[S]` type because shared fields are stored directly on the async logger value instead of being modeled as a separate sink wrapper.
- `ApplicationAsyncLogger` and `ApplicationTextAsyncLogger` are only alias names over concrete `AsyncLogger[...]` shapes, so they keep the same lifecycle, queue, failure, and state helpers without adding a wrapper layer.
@@ -54,15 +54,10 @@ Detailed rules explaining key parameters and behaviors
- `src-async` is designed for `native / llvm / js / wasm / wasm-gc`, but current release-facing local verification is stronger for `native / js / wasm / wasm-gc` than for `llvm`.
- `llvm` should currently be read as experimental and locally unverified in this environment rather than as a stable checked target.
- `flush` is used only when batch or shutdown policy wants explicit flushing.
- The callback expresses attempted flush timing and failure, not a returned progress count contract.
- If the supplied flush callback raises, worker failure state is recorded through `has_failed()` and `last_error()`.
- `wait_idle()` is failure-aware rather than a pure backlog-to-zero guarantee. If a worker failure sets `has_failed=true`, waiting stops early and the logger can still report `pending_count() > 0` until later cleanup or restart work happens.
- A later `run()` attempt starts by clearing stale failure state back to `has_failed=false` and `last_error=""` before it resumes draining any backlog still left in the queue.
- `state()` exposes the stronger lifecycle conclusion through `phase`, plus derived reads such as `backlog_retained`, `can_rerun`, and `terminal` so callers do not have to infer these states from raw flag combinations.
- Late log attempts after closure are rejected in the shared async log path before patch/filter work runs, so post-close side effects no longer vary by backend.
- `run()` now enforces a single-worker contract and raises `AsyncLoggerAlreadyRunning` when a second worker startup is attempted for the same live logger.
- `run()` also rejects already-closed loggers with `AsyncLoggerClosed`, which keeps rerun semantics aligned with the stronger lifecycle model: rerun is for retained `failed` backlog, not for terminal closed phases.
- `shutdown()` now always waits for any active worker to finish and converts retained post-failure backlog into dropped records before returning.
- The exact behavior of late log attempts after closure is runtime-dependent, so callers should use lifecycle helpers like `is_closed()` and `shutdown()` instead of assuming identical post-close enqueue semantics everywhere.
- Queue overflow behavior depends on `AsyncOverflowPolicy`.
### How to Use
@@ -130,7 +125,6 @@ e.g.:
- If the logger is closed, further enqueue attempts stop being normal active logging operations.
- If queue drain fails internally, runtime state can reflect that through `has_failed()` and `last_error()`.
- If a second worker startup is attempted while `is_running()` is already true, `run()` raises `AsyncLoggerAlreadyRunning`.
### Notes
+3 -3
View File
@@ -13,12 +13,12 @@ key-word:
## Async-runtime-state-to-json
Convert `AsyncRuntimeState` into a `Json`. This helper exports the async runtime mode and background worker capability in a structured form.
Convert `AsyncRuntimeState` into a `JsonValue`. This helper exports the async runtime mode and background worker capability in a structured form.
### Interface
```moonbit
pub fn async_runtime_state_to_json(state : AsyncRuntimeState) -> Json {}
pub fn async_runtime_state_to_json(state : AsyncRuntimeState) -> @json_parser.JsonValue {}
```
#### input
@@ -27,7 +27,7 @@ pub fn async_runtime_state_to_json(state : AsyncRuntimeState) -> Json {}
#### output
- `Json` - Structured JSON representation of the runtime state.
- `JsonValue` - Structured JSON representation of the runtime state.
### Explanation
-3
View File
@@ -15,8 +15,6 @@ key-word:
Build a `ConfiguredLogger` from `LoggerConfig`. This is the main config-to-runtime bridge for synchronous logging and is the builder used before async wrapping in config-driven async flows.
At the public `src` layer, this API is the entry facade that consumes the shared config model owned by `src/config_model` and produces a `ConfiguredLogger` backed by `src/runtime.RuntimeSink`.
### Interface
```moonbit
@@ -36,7 +34,6 @@ pub fn build_logger(config : LoggerConfig) -> ConfiguredLogger {}
Detailed rules explaining key parameters and behaviors
- `build_logger(...)` first constructs a base `RuntimeSink` from `config.sink`, then applies `config.queue` when present, and finally builds `Logger::new(...)` with `config.min_level`, `config.target`, and `config.timestamp`.
- The returned file-control and file-diagnostics helpers are still facade methods over `RuntimeSink`, which in turn delegates file behavior to `src/file_runtime` and file model values to `src/file_model`.
- The returned logger still supports normal logging methods because `ConfiguredLogger` is `Logger[RuntimeSink]`.
- The returned logger also keeps inherited logger target behavior such as `with_target(...)`, `child(...)`, and per-call `target=` overrides on `log(...)`.
- That means `log(..., target=...)` can override the target for one write, while severity helpers such as `info(...)`, `warn(...)`, and `error(...)` continue to use the stored logger target unless a derived logger was created first with `with_target(...)` or `child(...)`.
+5 -6
View File
@@ -2,8 +2,8 @@
name: config-error
group: api
category: config
update-time: 20260707
description: Public config parsing error re-exported from config_model for synchronous config-loading helpers.
update-time: 20260613
description: Public config parsing error alias used by synchronous config-loading helpers.
key-word:
- config
- error
@@ -13,12 +13,12 @@ key-word:
## Config-error
`ConfigError` is the public error type raised by synchronous config parsing helpers. On the root `src` facade, it is re-exported from `src/config_model`, which is the real owner of the structured config error definition.
`ConfigError` is the public error type raised by synchronous config parsing helpers. It is a direct alias to the internal config error definition and currently exposes a single structured error case for invalid input.
### Interface
```moonbit
pub using @config_model { type ConfigError }
pub type ConfigError = @utils.ConfigError
```
#### output
@@ -29,8 +29,7 @@ pub using @config_model { type ConfigError }
Detailed rules explaining key parameters and behaviors
- This root surface is a re-export, not the concrete owner definition.
- The concrete error lives in `@config_model.ConfigError`, not in `@utils`.
- This is a type alias, not a separate public wrapper.
- The current public error case is `ConfigError::InvalidConfig(message)`.
- The alias is used by parsing helpers such as `parse_logger_config_text(...)` and by lower-level config parsing routines beneath it.
- Error messages describe concrete schema problems such as invalid JSON, wrong value types, unsupported enum text, or missing required values for a chosen sink kind.
+8 -14
View File
@@ -2,8 +2,8 @@
name: configured-logger-close
group: api
category: runtime
update-time: 20260707
description: Close the configured runtime logger sink and return whether the wrapped RuntimeSink close path succeeded.
update-time: 20260613
description: Close the configured runtime logger sink and return whether the wrapped RuntimeSink reported a successful close action.
key-word:
- logger
- runtime
@@ -27,7 +27,7 @@ pub fn ConfiguredLogger::close(self : ConfiguredLogger) -> Bool {}
#### output
- `Bool` - Whether the wrapped `RuntimeSink::close(...)` call reported a successful close path.
- `Bool` - Whether the wrapped `RuntimeSink::close(...)` call reported a successful close action.
### Explanation
@@ -35,11 +35,9 @@ Detailed rules explaining key parameters and behaviors
- This helper delegates directly to `self.sink.close()`.
- Plain file sinks forward to `FileSink::close()` through `RuntimeSink`.
- Queue-backed file sinks now follow the same safe teardown path as `file_close()`: they first try to drain the queue, then flush the wrapped inner file sink, then close it.
- On queued file sinks, the returned `Bool` is `true` only when that whole teardown path succeeds without introducing new file failures.
- Plain console-style sinks return `true` as a no-op success because they do not expose a meaningful close step here.
- Queue-wrapped console-style sinks now use drain-first teardown before returning `true`.
- For `QueuedConsole`, `QueuedJsonConsole`, and `QueuedTextConsole`, success means the queued backlog was consumed to zero.
- Queue-backed file sinks close the wrapped file sink instead of only the queue wrapper.
- Generic `close()` on queued file sinks does not drain pending queue entries first; it closes the wrapped file sink directly.
- Console-style sinks and queue-wrapped console-style sinks return `true` as a no-op success because they do not expose a meaningful close step here.
- For file-backed configured loggers, later `close()` calls return `false` after the wrapped file handle has already been cleared.
### How to Use
@@ -71,16 +69,12 @@ e.g.:
- If the configured logger shares the same wrapped runtime sink state with another facade and one path already closed that file-backed sink, a later close attempt returns `false`.
- If callers need a file-specific close path with queue flush nuances, `file_close()` may still be the clearer API.
- On queued file sinks, `true` still does not mean the records are guaranteed to be durable beyond what the current backend can report; it means the queue-drain, file-flush, and file-close path completed without a newly observed file failure.
- On queued non-file sinks, `true` means the queued backlog was consumed before teardown completed.
- If callers need a file-specific close path with queue flush nuances, `file_close()` may be the better API.
### Notes
1. This is the generic configured runtime close helper.
2. Generic `close()` is now safe for queue-backed runtime sinks and no longer skips queued records silently.
2. Prefer `file_close()` when the configured sink shape is file-backed and queued records should be flushed before teardown.
3. Converting the same configured logger through wrapper paths such as library projection still shares the wrapped runtime sink state, so close effects are visible across those facades.
@@ -1,79 +0,0 @@
---
name: configured-logger-drain-progress
group: api
category: runtime
update-time: 20260707
description: Return a structured generic drain progress snapshot for a ConfiguredLogger through RuntimeSink without collapsing queue and plain-file fallback semantics into one Int.
key-word:
- logger
- runtime
- drain
- public
---
## Configured-logger-drain-progress
Return a structured generic drain progress snapshot for a `ConfiguredLogger`. This is the recommended configured runtime wrapper over `RuntimeSink::drain_progress(...)` when code wants truthful generic progress instead of the compatibility `Int` returned by `drain()`.
### Interface
```moonbit
pub fn ConfiguredLogger::drain_progress(
self : ConfiguredLogger,
max_items~ : Int = -1,
) -> RuntimeSinkProgress {}
```
#### input
- `self : ConfiguredLogger` - Config-driven runtime logger whose generic drain progress should be observed.
- `max_items : Int` - Optional upper bound on drained queued items. Negative values mean no explicit bound.
#### output
- `RuntimeSinkProgress` - Structured progress snapshot returned by the wrapped `RuntimeSink::drain_progress(...)` call.
### Explanation
Detailed rules explaining key parameters and behaviors
- This helper delegates directly to `self.sink.drain_progress(max_items=max_items)`.
- Queue-wrapped sinks report drained queued items through `queue_advanced_count`.
- Plain file sinks report the generic fallback flush step through `file_flush_step_count`.
- Plain console-style sinks return a zeroed snapshot.
- This helper keeps configured-runtime drain behavior explicit without forcing callers to interpret one mixed `Int`.
### How to Use
Here are some specific examples provided.
#### When Need Recommended Bounded Generic Drain Progress On A Config-built Logger
When queued config-built output should be advanced in chunks with explicit semantics:
```moonbit
let progress = logger.drain_progress(max_items=16)
```
In this example, queue advancement and plain-file fallback stay separated.
#### When Need Full Manual Generic Drain Progress
When config-built support code should empty runtime queue work while keeping shape information:
```moonbit
let progress = logger.drain_progress()
```
In this example, the structured result still tells whether the logger was queue-backed or plain file-backed.
### Error Case
e.g.:
- If the configured runtime sink is not queue-backed, the snapshot may stay zeroed or use the plain-file fallback field.
- If callers need file-specific success semantics after queue delivery, `file_flush()` is the better API.
### Notes
1. Prefer `drain_progress()` over `drain()` in new configured-runtime code.
2. Use `pending_count()` together with this helper when remaining backlog should also be observed.
+14 -21
View File
@@ -2,8 +2,8 @@
name: configured-logger-drain
group: api
category: runtime
update-time: 20260707
description: Compatibility configured runtime drain helper that still returns one Int by collapsing generic queue progress and plain-file fallback steps.
update-time: 20260613
description: Drain queued work from a configured runtime logger with optional item limits through RuntimeSink.
key-word:
- logger
- runtime
@@ -13,7 +13,7 @@ key-word:
## Configured-logger-drain
Drain queued work from a `ConfiguredLogger` and return one compatibility count. This helper is still available for older code, but new configured-runtime code should prefer `drain_progress()` because it exposes queue advancement and plain-file fallback steps separately.
Drain queued work from a `ConfiguredLogger`. This helper is the configured logger wrapper over `RuntimeSink::drain(...)` when config-driven queue wrapping should be advanced in a controlled, bounded way.
### Interface
@@ -28,17 +28,16 @@ pub fn ConfiguredLogger::drain(self : ConfiguredLogger, max_items~ : Int = -1) -
#### output
- `Int` - Compatibility count returned by the wrapped `RuntimeSink::drain(...)` call.
- `Int` - Count returned by the wrapped `RuntimeSink::drain(...)` call.
### Explanation
Detailed rules explaining key parameters and behaviors
- This helper delegates directly to `self.sink.drain(max_items=max_items)`.
- Under the hood, `RuntimeSink::drain()` now rebuilds one compatibility count from `drain_progress()`.
- Queue-wrapped sinks still report drained queued items through that compatibility count.
- Plain file sinks still report the generic fallback flush step as `1` or `0`.
- Plain console-style sinks still return `0`.
- Queue-wrapped sinks forward to the concrete queue sink's `drain(...)` behavior and may drain up to `max_items` records.
- Plain file sinks fall back to `FileSink::flush()` behavior through `RuntimeSink` and return `1` or `0`.
- Plain console-style sinks return `0` because they do not own a drainable queue here.
### How to Use
@@ -46,37 +45,31 @@ Here are some specific examples provided.
#### When Need Bounded Queue Progress
When older code already expects one numeric drain count from a config-built logger:
When queued output should be advanced in chunks:
```moonbit
let drained = logger.drain(max_items=16)
```
In this example, callers still limit how much queued work is processed in one step while keeping the legacy return shape.
In this example, callers limit how much queued work is processed in one step.
#### When Need Full Manual Drain
When code should keep the older full-drain compatibility path:
When the configured queue should be emptied explicitly:
```moonbit
ignore(logger.drain())
```
In this example, the configured runtime logger drains without changing the legacy return shape.
In this example, the configured runtime logger drains without imposing an item cap.
### Error Case
e.g.:
- If the configured runtime sink is not queue-backed, draining may return `0` or follow the plain-file flush fallback.
- If callers need truthful generic progress semantics, `drain_progress()` is the better API.
- If callers only need generic flush semantics, `flush_progress()` may be the simpler structured API.
- If callers need file-specific success semantics after draining a queued file logger, they should inspect failure counters or use `file_flush()` for the file-specific path.
- If callers only need generic flush semantics, `flush()` may be the simpler API.
### Notes
1. Treat this method as a compatibility helper for older numeric code.
1. Prefer this helper when queue progress should be bounded or observable.
2. Prefer `drain_progress()` in new configured-runtime code.
3. Use `pending_count()` to inspect remaining backlog after the drain call when the configured sink is queue-backed.
2. Use `pending_count()` to inspect remaining backlog after the drain call when the configured sink is queue-backed.
+3 -7
View File
@@ -2,7 +2,7 @@
name: configured-logger-file-available
group: api
category: runtime
update-time: 20260707
update-time: 20260512
description: Read whether the configured runtime logger currently has an available file sink behind its runtime sink shape.
key-word:
- logger
@@ -36,8 +36,6 @@ Detailed rules explaining key parameters and behaviors
- File-backed runtime sinks report actual file availability through the wrapped `RuntimeSink`.
- Queued file sinks still expose the availability of their wrapped inner file sink.
- Non-file sinks report `false`.
- This means `false` currently merges two different situations: “not file-backed” and “file-backed but currently unavailable”.
- Use `file_path_or_none()`, `file_policy_or_none()`, `file_default_policy_or_none()`, `file_state_or_none()`, or `file_runtime_state()` when callers need truthful file-semantics detection.
- This helper delegates to the runtime sink and does not mutate logger state.
### How to Use
@@ -69,12 +67,10 @@ In this example, callers can decide whether a recovery action is needed.
e.g.:
- If the configured sink is not file-backed, the method returns `false`.
- If callers need to distinguish “not file-backed from “file-backed but unavailable”, use one of the truthful `*_or_none()` helpers or `file_runtime_state()`.
- If callers need detailed failure counters rather than a simple availability flag, `file_state_or_none()` or `file_runtime_state()` is the better API.
- If callers need detailed failure counters rather than a simple availability flag, `file_state()` or `file_runtime_state()` is the better API.
### Notes
1. Use this helper for lightweight file sink health checks.
2. Pair it with reopen and failure-counter APIs when diagnosing file sink problems, but prefer the truthful `*_or_none()` helpers when file semantics themselves must be checked.
2. Pair it with reopen and failure-counter APIs when diagnosing file sink problems.
@@ -2,8 +2,8 @@
name: configured-logger-file-clear-rotation
group: api
category: runtime
update-time: 20260707
description: Clear the rotation policy used by the configured runtime file sink.
update-time: 20260512
description: Disable runtime rotation on the configured file-backed logger sink.
key-word:
- logger
- runtime
@@ -13,7 +13,7 @@ key-word:
## Configured-logger-file-clear-rotation
Clear the rotation policy used by a `ConfiguredLogger` file sink.
Disable runtime rotation on a `ConfiguredLogger` file sink. This helper is the direct shortcut for clearing rotation policy.
### Interface
@@ -23,7 +23,7 @@ pub fn ConfiguredLogger::file_clear_rotation(self : ConfiguredLogger) -> Bool {}
#### input
- `self : ConfiguredLogger` - Config-driven runtime logger whose file rotation policy should be cleared.
- `self : ConfiguredLogger` - Config-driven runtime logger whose rotation policy should be cleared.
#### output
@@ -34,12 +34,41 @@ pub fn ConfiguredLogger::file_clear_rotation(self : ConfiguredLogger) -> Bool {}
Detailed rules explaining key parameters and behaviors
- File-backed sinks clear their runtime rotation policy through the wrapped `RuntimeSink`.
- Queued file sinks clear the wrapped inner file sink rotation policy only when no queued records are pending.
- Queued file sinks forward the update to the wrapped inner file sink.
- Non-file sinks return `false`.
- If a queued file sink still has pending records, the update is rejected and returns `false` so already queued records are not later written under a different rotation policy than the one they were queued under.
- This helper is equivalent in intent to setting rotation to `None`, but is clearer at the call site.
### How to Use
Here are some specific examples provided.
#### When Need To Disable Rotation Explicitly
When runtime file rotation should be turned off:
```moonbit
ignore(logger.file_clear_rotation())
```
In this example, rotation policy is removed directly.
#### When Need A Clear Intent Shortcut
When code should make the disable-rotation intent obvious:
```moonbit
let ok = logger.file_clear_rotation()
```
In this example, the call site reads more clearly than a generic config setter.
### Error Case
e.g.:
- If the configured sink is not file-backed, the method returns `false`.
- If callers need to switch to another rotation config rather than disable rotation, `file_set_rotation(...)` is the better API.
### Notes
1. Use this helper when runtime rotation policy should be removed without rebuilding the logger.
1. Use this helper when the desired effect is simply “rotation off”.
2. On queued file sinks, clear pending records first so policy mutation does not retroactively affect already queued writes.
2. It is clearer than passing `None` through a broader setter when intent matters.
+6 -9
View File
@@ -2,8 +2,8 @@
name: configured-logger-file-close
group: api
category: runtime
update-time: 20260707
description: Close the file sink behind a configured runtime logger when one is present, with queued-file success tied to safe drain-flush-close behavior.
update-time: 20260512
description: Close the file sink behind a configured runtime logger when one is present.
key-word:
- logger
- runtime
@@ -27,15 +27,14 @@ pub fn ConfiguredLogger::file_close(self : ConfiguredLogger) -> Bool {}
#### output
- `Bool` - Whether the file-specific close path succeeded.
- `Bool` - Whether the underlying file close succeeded.
### Explanation
Detailed rules explaining key parameters and behaviors
- Plain file sinks forward directly to file close behavior through the wrapped `RuntimeSink`.
- Queued file sinks first drain the queue, then flush the wrapped inner file sink, then close it.
- For queued file sinks, the returned `Bool` is `true` only when that whole path succeeds and no new write, flush, or rotation failures are observed during the drain-flush-close step.
- Queued file sinks flush queue work before closing the wrapped inner file sink.
- Non-file sinks return `false`.
- This helper is narrower than generic `close()` because it specifically targets file sink shutdown.
- After a file-backed configured logger has already cleared its file handle, later `file_close()` calls return `false`.
@@ -60,7 +59,7 @@ When application code wants the file close outcome directly:
let closed = logger.file_close()
```
In this example, the result describes the file-specific close path rather than generic sink close behavior.
In this example, the result describes file close behavior rather than generic sink close behavior.
### Error Case
@@ -71,12 +70,10 @@ e.g.:
- If callers only need generic sink teardown, `close()` is the broader API.
- On queued file sinks, `true` still does not mean a stronger durability contract than the current backend can report; it means the safe drain-flush-close path completed without a newly observed file failure.
### Notes
1. Prefer this helper when file-backed runtime behavior matters specifically.
2. Generic `close()` now uses the same safe queued-file teardown path.
2. Queued file sinks flush pending records before closing the file, unlike generic `close()`.
3. Library or application facades derived from the same configured runtime logger still observe the same underlying file-close state.
@@ -1,82 +0,0 @@
---
name: configured-logger-file-default-policy-or-none
group: api
category: runtime
update-time: 20260707
description: Read the default runtime file policy from a ConfiguredLogger only when it is actually file-backed.
key-word:
- logger
- runtime
- file
- truthful
---
## Configured-logger-file-default-policy-or-none
Read the default runtime file policy from a `ConfiguredLogger` only when it is actually file-backed.
The returned `FileSinkPolicy` value is owned by `src/file_model`; this configured-logger surface is a facade over `Logger[@runtime.RuntimeSink]` and avoids fabricating that model on non-file variants.
This is the truthful companion to `file_default_policy()`. Prefer it when default-policy inspection should not fabricate a fallback object on non-file sinks.
### Interface
```moonbit
pub fn ConfiguredLogger::file_default_policy_or_none(self : ConfiguredLogger) -> FileSinkPolicy? {}
```
#### input
- `self : ConfiguredLogger` - Config-driven runtime logger whose default file policy should be inspected.
#### output
- `FileSinkPolicy?` - `Some(policy)` when the configured sink is file-backed, otherwise `None`.
### Explanation
Detailed rules explaining key parameters and behaviors
- File-backed sinks return `Some(default_policy)` through the wrapped `RuntimeSink`.
- Queued file sinks forward the wrapped inner file sink default policy as `Some(default_policy)`.
- The wrapped value is the shared `@file_model.FileSinkPolicy` model, not a configured-logger-owned concrete type.
- Non-file sinks return `None`.
- This helper is useful when callers need to compare runtime drift or restore defaults without fabricating file semantics.
### How to Use
Here are some specific examples provided.
#### When Need Truthful Baseline Policy Visibility
When tooling should inspect defaults only for real file-backed sinks:
```moonbit
let defaults = logger.file_default_policy_or_none()
```
In this example, `None` means the configured logger has no file default policy.
#### When Compare Current And Default Policy Truthfully
When diagnostics should avoid fallback policy objects:
```moonbit
match (logger.file_policy_or_none(), logger.file_default_policy_or_none()) {
(Some(current), Some(defaults)) => ignore((current, defaults))
_ => ()
}
```
In this example, comparisons happen only when real file semantics exist.
### Error Case
e.g.:
- If the configured sink is not file-backed, the method returns `None`.
- If callers only need a drift boolean, `file_policy_matches_default()` remains simpler.
### Notes
1. Prefer this helper over `file_default_policy()` for truthful runtime diagnostics.
2. `file_default_policy()` remains available as the compatibility fallback API.
@@ -2,8 +2,8 @@
name: configured-logger-file-default-policy
group: api
category: runtime
update-time: 20260707
description: Read the initial default file policy associated with a configured logger, with a compatibility fallback for non-file sinks.
update-time: 20260512
description: Read the initial default file policy associated with a configured file-backed logger.
key-word:
- logger
- runtime
@@ -15,10 +15,6 @@ key-word:
Read the initial default file policy associated with a `ConfiguredLogger`. This helper exposes the baseline file policy captured when the runtime sink was created.
The returned `FileSinkPolicy` value is owned by `src/file_model`; this configured-logger surface is a facade over `Logger[@runtime.RuntimeSink]` and delegates default-policy reads to the wrapped `RuntimeSink`.
`file_default_policy()` is the compatibility form. For truthful file-semantics detection, prefer `file_default_policy_or_none()`.
### Interface
```moonbit
@@ -39,10 +35,7 @@ Detailed rules explaining key parameters and behaviors
- File-backed sinks return the default policy captured at creation time through the wrapped `RuntimeSink`.
- Queued file sinks forward the default policy from the wrapped inner file sink.
- The returned policy object itself is the shared `@file_model.FileSinkPolicy` model, not a configured-logger-owned concrete type.
- Non-file sinks return the same neutral fallback policy value produced by `RuntimeSink::file_default_policy()`.
- This fallback keeps older callers source-compatible, but it is not a real file default policy.
- New diagnostic or recovery code should prefer `file_default_policy_or_none()`.
- This helper is useful when callers need to compare runtime drift or restore defaults later.
### How to Use
@@ -72,12 +65,10 @@ In this example, callers can reason about “factory” file policy separately f
e.g.:
- If the configured sink is not file-backed, the return value is a neutral fallback policy.
- If callers need a truthful file-semantics check, use `file_default_policy_or_none()`.
- If callers only need to know whether runtime drift exists, `file_policy_matches_default()` is the simpler API.
### Notes
1. Use this helper when the original file policy matters operationally.
2. It complements `file_policy()` and `file_reset_policy()`, while `file_default_policy_or_none()` is the truthful diagnostic form.
2. It complements `file_policy()` and `file_reset_policy()`.
+8 -10
View File
@@ -2,8 +2,8 @@
name: configured-logger-file-flush
group: api
category: runtime
update-time: 20260707
description: Flush the file sink behind a configured runtime logger when one is present, with queued-file success tied to both queue drain and file flush outcome.
update-time: 20260614
description: Flush the file sink behind a configured runtime logger when one is present.
key-word:
- logger
- runtime
@@ -27,16 +27,16 @@ pub fn ConfiguredLogger::file_flush(self : ConfiguredLogger) -> Bool {}
#### output
- `Bool` - Whether the file-specific flush path succeeded.
- `Bool` - Whether the underlying file flush succeeded.
### Explanation
Detailed rules explaining key parameters and behaviors
- Plain file sinks forward directly to file flush behavior through the wrapped `RuntimeSink`.
- Queued file sinks first drain queued records, then flush the wrapped inner file sink.
- For queued file sinks, the returned `Bool` is `true` only when all queued records were consumed, the final file flush succeeded, and no new write, flush, or rotation failures were observed during that flush path.
- For queued file sinks, this step may also be the point where queued records finally hit the inner file sink, so failure counters can change here even if earlier log calls only queued records.
- Queued file sinks first flush queued records, then flush the wrapped inner file sink.
- For queued file sinks, the returned `Bool` comes from the inner file flush rather than the queue flush step.
- For queued file sinks, this step may also be the point where queued records finally hit the inner file sink, so write-failure counters can change here even if earlier log calls only queued records.
- Non-file sinks return `false`.
- This helper is narrower than generic `flush()` because it targets file sink behavior specifically.
- After a file-backed configured logger has already cleared its file handle, later `file_flush()` calls return `false`.
@@ -61,7 +61,7 @@ When code should branch on the outcome of a file flush:
let ok = logger.file_flush()
```
In this example, callers can distinguish file-specific flush success from a non-file sink shape.
In this example, callers can distinguish file flush success from a non-file sink shape.
### Error Case
@@ -72,12 +72,10 @@ e.g.:
- If callers want generic queue or sink advancement instead of file-specific behavior, `flush()` is the broader API.
- On queued file sinks, a `false` result may still mean queue consumption happened but file delivery observed a new failure.
### Notes
1. Prefer this helper when the configured sink is known to be file-backed.
2. Queued file sinks may perform both queue drain and file flush work here, including surfacing delayed failures from previously queued records.
2. Queued file sinks may perform both queue flush and file flush work here, including surfacing delayed write failures from previously queued records.
3. Library or application facades derived from the same configured runtime logger still observe the same underlying file-flush availability state.
@@ -1,79 +0,0 @@
---
name: configured-logger-file-path-or-none
group: api
category: runtime
update-time: 20260707
description: Read the effective file path from a ConfiguredLogger only when it is actually file-backed.
key-word:
- logger
- runtime
- file
- truthful
---
## Configured-logger-file-path-or-none
Read the effective file path from a `ConfiguredLogger` only when it is actually file-backed.
This is the truthful companion to `file_path()`. Prefer it for diagnostics, branching, and recovery logic that must distinguish “not file-backed” from compatibility fallbacks.
### Interface
```moonbit
pub fn ConfiguredLogger::file_path_or_none(self : ConfiguredLogger) -> String? {}
```
#### input
- `self : ConfiguredLogger` - Config-driven runtime logger whose file path should be inspected.
#### output
- `String?` - `Some(path)` when the configured sink is file-backed, otherwise `None`.
### Explanation
Detailed rules explaining key parameters and behaviors
- File-backed sinks return `Some(path)` through the wrapped `RuntimeSink`.
- Queued file sinks forward the wrapped inner file sink path as `Some(path)`.
- Non-file sinks return `None`.
- This helper is observation-only and does not mutate logger state.
### How to Use
Here are some specific examples provided.
#### When Need Truthful File-backed Detection
When code should branch only if file semantics really exist:
```moonbit
match logger.file_path_or_none() {
Some(path) => println(path)
None => ()
}
```
In this example, `None` means the configured logger is not file-backed.
#### When Need Path Diagnostics Without Fallback Values
When support output should avoid compatibility placeholders:
```moonbit
let maybe_path = logger.file_path_or_none()
```
In this example, callers can keep “no file semantics” distinct from a real path.
### Error Case
e.g.:
- If the configured sink is not file-backed, the method returns `None`.
- If callers need the broader file snapshot or queue context, prefer `file_state_or_none()` or `file_runtime_state()`.
### Notes
1. Prefer this helper over `file_path()` for truthful runtime diagnostics.
2. `file_path()` remains available as the compatibility fallback API.
+4 -10
View File
@@ -2,8 +2,8 @@
name: configured-logger-file-path
group: api
category: runtime
update-time: 20260707
description: Read the effective file path used by the configured runtime logger, with a compatibility fallback for non-file sinks.
update-time: 20260512
description: Read the effective file path used by the configured runtime logger when it is file-backed.
key-word:
- logger
- runtime
@@ -15,8 +15,6 @@ key-word:
Read the effective file path used by a `ConfiguredLogger`. This helper is useful for diagnostics, support output, and confirming which file-backed runtime sink is active.
`file_path()` is the compatibility form. For truthful file-semantics detection, prefer `file_path_or_none()`.
### Interface
```moonbit
@@ -38,8 +36,6 @@ Detailed rules explaining key parameters and behaviors
- File-backed sinks return their current file path through the wrapped `RuntimeSink`.
- Queued file sinks forward the wrapped inner file sink path.
- Non-file sinks return an empty string.
- This fallback keeps older callers source-compatible, but it does not truthfully express whether file semantics exist.
- New diagnostic code should prefer `file_path_or_none()`.
- This helper is observation-only and does not modify file state.
### How to Use
@@ -69,12 +65,10 @@ In this example, the path can be surfaced without reading broader runtime state.
e.g.:
- If the configured sink is not file-backed, the method returns an empty string.
- If callers need a truthful file-semantics check, use `file_path_or_none()`.
- If callers need richer file status than just the path, `file_state_or_none()` or `file_runtime_state()` is the better API.
- If callers need richer file status than just the path, `file_state()` or `file_runtime_state()` is the better API.
### Notes
1. Use this helper for direct runtime path visibility.
2. Empty string is a compatibility fallback; `file_path_or_none()` is the recommended truthful API.
2. Empty string usually means the configured sink is not file-backed.
@@ -1,79 +0,0 @@
---
name: configured-logger-file-policy-or-none
group: api
category: runtime
update-time: 20260707
description: Read the current runtime file policy from a ConfiguredLogger only when it is actually file-backed.
key-word:
- logger
- runtime
- file
- truthful
---
## Configured-logger-file-policy-or-none
Read the current runtime file policy from a `ConfiguredLogger` only when it is actually file-backed.
This is the truthful companion to `file_policy()`. Prefer it for diagnostics and recovery logic that must avoid fallback policy objects.
### Interface
```moonbit
pub fn ConfiguredLogger::file_policy_or_none(self : ConfiguredLogger) -> FileSinkPolicy? {}
```
#### input
- `self : ConfiguredLogger` - Config-driven runtime logger whose current file policy should be inspected.
#### output
- `FileSinkPolicy?` - `Some(policy)` when the configured sink is file-backed, otherwise `None`.
### Explanation
Detailed rules explaining key parameters and behaviors
- File-backed sinks return `Some(current_policy)` through the wrapped `RuntimeSink`.
- Queued file sinks forward the wrapped inner file sink policy as `Some(current_policy)`.
- Non-file sinks return `None`.
- This helper is broader than `file_append_mode()` or `file_auto_flush()` because it returns the whole policy object without fallback synthesis.
### How to Use
Here are some specific examples provided.
#### When Need Truthful Policy Diagnostics
When diagnostics should inspect file policy only if file semantics exist:
```moonbit
match logger.file_policy_or_none() {
Some(policy) => ignore(policy)
None => ()
}
```
In this example, `None` means there is no real file policy to inspect.
#### When Need Compatibility-free Recovery Decisions
When recovery logic should not treat a fallback object as real state:
```moonbit
let maybe_policy = logger.file_policy_or_none()
```
In this example, callers can distinguish missing file semantics from a live policy snapshot.
### Error Case
e.g.:
- If the configured sink is not file-backed, the method returns `None`.
- If callers need default-policy comparison, pair it with `file_default_policy_or_none()`.
### Notes
1. Prefer this helper over `file_policy()` for truthful runtime diagnostics.
2. `file_policy()` remains available as the compatibility fallback API.
+3 -12
View File
@@ -2,8 +2,8 @@
name: configured-logger-file-policy
group: api
category: runtime
update-time: 20260707
description: Read the current runtime file policy from a configured logger, with a compatibility fallback for non-file sinks.
update-time: 20260512
description: Read the current runtime file policy from a configured file-backed logger.
key-word:
- logger
- runtime
@@ -15,10 +15,6 @@ key-word:
Read the current runtime file policy from a `ConfiguredLogger`. This helper exposes the active append, auto-flush, and rotation settings as one policy object.
The returned `FileSinkPolicy` value is owned by `src/file_model`; this configured-logger surface is a facade over `Logger[@runtime.RuntimeSink]` and delegates policy reads to the wrapped `RuntimeSink`, which in turn reaches file-backed variants that ultimately use `src/file_runtime.FileSink`.
`file_policy()` is the compatibility form. For truthful file-semantics detection, prefer `file_policy_or_none()`.
### Interface
```moonbit
@@ -39,10 +35,7 @@ Detailed rules explaining key parameters and behaviors
- File-backed sinks return their current runtime file policy through the wrapped `RuntimeSink`.
- Queued file sinks forward the policy from the wrapped inner file sink.
- The returned policy object itself is the shared `@file_model.FileSinkPolicy` model, not a configured-logger-owned concrete type.
- Non-file sinks return the same neutral fallback policy value produced by `RuntimeSink::file_policy()`.
- This fallback keeps older callers source-compatible, but it is not a real file policy.
- New diagnostic or recovery code should prefer `file_policy_or_none()`.
- This helper is broader than `file_append_mode()` or `file_auto_flush()` because it returns the whole policy object.
### How to Use
@@ -73,12 +66,10 @@ In this example, callers can compare current runtime settings with the initial p
e.g.:
- If the configured sink is not file-backed, the return value is a neutral fallback policy rather than a real active file policy.
- If callers need a truthful file-semantics check, use `file_policy_or_none()`.
- If callers only need one field from the policy, a narrower helper may be simpler.
### Notes
1. Use this helper when file policy should be handled as one object.
2. Pair it with `file_set_policy(...)` for roundtrip-style policy management, or prefer `file_policy_or_none()` for truthful diagnostics.
2. Pair it with `file_set_policy(...)` for roundtrip-style policy management.
+3 -6
View File
@@ -2,7 +2,7 @@
name: configured-logger-file-reopen
group: api
category: runtime
update-time: 20260707
update-time: 20260512
description: Reopen the file sink behind a configured runtime logger with an optional append-mode override.
key-word:
- logger
@@ -35,10 +35,9 @@ pub fn ConfiguredLogger::file_reopen(self : ConfiguredLogger, append~ : Bool? =
Detailed rules explaining key parameters and behaviors
- Plain file sinks reopen directly through the wrapped `RuntimeSink`.
- Queued file sinks forward reopen behavior to the wrapped inner file sink only when no queued records are pending.
- Queued file sinks forward reopen behavior to the wrapped inner file sink.
- `append=None` preserves current reopen policy, while `Some(true/false)` overrides append mode.
- Non-file sinks return `false`.
- If a queued file sink still has pending records, reopen is rejected and returns `false` so queued records are not later written under a different reopen mode than the one they were queued under.
### How to Use
@@ -69,10 +68,8 @@ e.g.:
- If callers only need the current configured policy, `file_reopen_with_current_policy()` may be the clearer API.
- If a queued file sink still has pending records, callers should flush or close it first before attempting reopen.
### Notes
1. Use this helper for explicit recovery flows.
2. On queued file sinks, clear pending records first so reopen semantics stay stable for already queued writes.
2. Pair it with `file_available()` and failure counters when diagnosing reopen behavior.
@@ -2,8 +2,8 @@
name: configured-logger-file-reset-policy
group: api
category: runtime
update-time: 20260707
description: Reset the runtime file policy of a configured logger back to its captured defaults.
update-time: 20260512
description: Reset the runtime file policy of a configured file-backed logger back to its original defaults.
key-word:
- logger
- runtime
@@ -13,7 +13,7 @@ key-word:
## Configured-logger-file-reset-policy
Reset the runtime file policy of a `ConfiguredLogger` back to its captured defaults.
Reset the runtime file policy of a `ConfiguredLogger` back to its original defaults. This helper restores append, auto-flush, and rotation policy together.
### Interface
@@ -21,17 +21,56 @@ Reset the runtime file policy of a `ConfiguredLogger` back to its captured defau
pub fn ConfiguredLogger::file_reset_policy(self : ConfiguredLogger) -> Bool {}
```
#### input
- `self : ConfiguredLogger` - Config-driven runtime logger whose file policy should be restored.
#### output
- `Bool` - Whether the reset was applied.
### Explanation
Detailed rules explaining key parameters and behaviors
- File-backed sinks restore their runtime default policy through the wrapped `RuntimeSink`.
- Queued file sinks restore the wrapped inner file sink default policy only when no queued records are pending.
- File-backed sinks restore their stored default file policy through the wrapped `RuntimeSink`.
- Queued file sinks forward the reset behavior to the wrapped inner file sink.
- Non-file sinks return `false`.
- If a queued file sink still has pending records, the reset is rejected and returns `false` so already queued records are not later written under a different policy than the one they were queued under.
- This helper is the inverse of runtime policy drift, not a generic reopen or flush action.
### How to Use
Here are some specific examples provided.
#### When Need To Undo Runtime Policy Changes
When file policy should return to the original configured defaults:
```moonbit
ignore(logger.file_reset_policy())
```
In this example, append, auto-flush, and rotation settings are restored together.
#### When Use Drift-aware Recovery
When reset should only happen after runtime changes:
```moonbit
if !logger.file_policy_matches_default() {
ignore(logger.file_reset_policy())
}
```
In this example, reset is only applied when runtime policy has diverged.
### Error Case
e.g.:
- If the configured sink is not file-backed, the method returns `false`.
- If callers need to restore only one setting, a narrower setter may be more appropriate than a full policy reset.
### Notes
1. Use this helper when runtime file policy should return to its captured defaults.
1. Use this helper when the original bundled file policy should be restored intact.
2. On queued file sinks, clear pending records first so policy mutation does not retroactively affect already queued writes.
2. It pairs naturally with `file_policy_matches_default()` and `file_default_policy()`.
@@ -15,8 +15,6 @@ key-word:
Read the current rotation configuration used by a `ConfiguredLogger` file sink. This helper exposes the active runtime rotation parameters when rotation is enabled.
The returned `FileRotation` value is owned by `src/file_model`; this configured-logger surface is a facade over `Logger[@runtime.RuntimeSink]` and delegates rotation reads to the wrapped `RuntimeSink`.
### Interface
```moonbit
@@ -37,7 +35,6 @@ Detailed rules explaining key parameters and behaviors
- File-backed sinks return their current rotation configuration when enabled through the wrapped `RuntimeSink`.
- Queued file sinks forward the config from the wrapped inner file sink.
- The returned rotation object itself is the shared `@file_model.FileRotation` model, not a configured-logger-owned concrete type.
- Non-file sinks return `None`.
- This helper is useful when callers need active runtime rotation parameters rather than only a boolean flag.
@@ -2,7 +2,7 @@
name: configured-logger-file-rotation-failures
group: api
category: runtime
update-time: 20260707
update-time: 20260512
description: Read the number of rotation failures recorded by the configured runtime file sink.
key-word:
- logger
@@ -13,7 +13,7 @@ key-word:
## Configured-logger-file-rotation-failures
Read the number of runtime file-rotation attempts whose critical file steps failed in a `ConfiguredLogger`.
Read the number of rotation failures recorded by a `ConfiguredLogger` file sink. This helper is useful when runtime rotation behavior should be observed operationally.
### Interface
@@ -36,7 +36,6 @@ Detailed rules explaining key parameters and behaviors
- File-backed sinks report their recorded rotation-failure count through the wrapped `RuntimeSink`.
- Queued file sinks forward the metric from the wrapped inner file sink.
- Non-file sinks return `0`.
- For file-backed paths, the counter covers incomplete rotations caused by critical remove/rename/reopen failures, not every possible file-health issue.
- The counter is cumulative until reset.
### How to Use
@@ -50,7 +49,7 @@ When support output should reveal whether rotation is failing:
let count = logger.file_rotation_failures()
```
In this example, the configured logger exposes whether runtime file rotation stopped completing its critical steps.
In this example, the configured logger exposes a focused metric for rotation-path health.
#### When Validate Runtime Rotation Tuning
@@ -59,7 +58,7 @@ When changed rotation settings should be checked in operation:
ignore(logger.file_rotation_failures())
```
In this example, callers can observe whether runtime rotation changes introduced incomplete rotations.
In this example, callers can observe whether runtime rotation changes introduced problems.
### Error Case
@@ -68,10 +67,8 @@ e.g.:
- If callers need both rotation config and failure metrics, they should combine this helper with `file_rotation_config()` or `file_state()`.
- This counter does not identify the exact remove/rename/reopen step that failed.
### Notes
1. Use this helper when diagnosing incomplete file rotations.
1. Use this helper when diagnosing file rotation reliability.
2. It is especially relevant when runtime rotation policy can change after startup.
@@ -15,8 +15,6 @@ key-word:
Read combined file and queue runtime state from a `ConfiguredLogger`. This helper is the richest file-specific diagnostics API on config-built runtime loggers.
The returned `RuntimeFileState` value is owned by `src/file_model`; this configured-logger surface is a facade over `Logger[@runtime.RuntimeSink]` and delegates runtime file-state reads to the wrapped `RuntimeSink`.
### Interface
```moonbit
@@ -37,7 +35,6 @@ Detailed rules explaining key parameters and behaviors
- File-backed sinks return `Some(RuntimeFileState)` through the wrapped `RuntimeSink`.
- Queued file sinks include both file status and queue metrics in the returned state.
- The returned snapshot object itself is the shared `@file_model.RuntimeFileState` model, not a configured-logger-owned concrete type.
- Non-file sinks return `None`.
- This helper is richer than `file_state()` because it can also surface queued backlog and dropped counts.
@@ -2,7 +2,7 @@
name: configured-logger-file-set-append-mode
group: api
category: runtime
update-time: 20260707
update-time: 20260512
description: Update the append-mode policy used by the configured runtime file sink for later reopen behavior.
key-word:
- logger
@@ -35,10 +35,9 @@ pub fn ConfiguredLogger::file_set_append_mode(self : ConfiguredLogger, append :
Detailed rules explaining key parameters and behaviors
- File-backed sinks update their stored append policy through the wrapped `RuntimeSink`.
- Queued file sinks forward the policy update to the wrapped inner file sink only when no queued records are pending.
- Queued file sinks forward the policy update to the wrapped inner file sink.
- This helper updates policy only; it does not force immediate reopen.
- Non-file sinks return `false`.
- If a queued file sink still has pending records, the update is rejected and returns `false` so already queued records are not later written under a different append policy than the one they were queued under.
### How to Use
@@ -70,10 +69,8 @@ e.g.:
- If callers need an immediate reopen as part of the same operation, one of the reopen helpers should be used afterward.
- If a queued file sink still has pending records, callers should flush or close it first before changing append mode.
### Notes
1. This helper changes stored policy, not live file-handle state by itself.
2. On queued file sinks, clear pending records first so staged reopen policy does not retroactively affect already queued writes.
2. It is useful when recovery logic wants to stage reopen behavior in advance.
@@ -2,7 +2,7 @@
name: configured-logger-file-set-auto-flush
group: api
category: runtime
update-time: 20260707
update-time: 20260512
description: Update the auto-flush policy used by the configured runtime file sink.
key-word:
- logger
@@ -35,10 +35,9 @@ pub fn ConfiguredLogger::file_set_auto_flush(self : ConfiguredLogger, enabled :
Detailed rules explaining key parameters and behaviors
- File-backed sinks update their runtime auto-flush policy through the wrapped `RuntimeSink`.
- Queued file sinks forward the update to the wrapped inner file sink only when no queued records are pending.
- Queued file sinks forward the update to the wrapped inner file sink.
- Non-file sinks return `false`.
- This helper changes policy only; it does not itself flush pending data.
- If a queued file sink still has pending records, the update is rejected and returns `false` so already queued records are not later written under a different auto-flush policy than the one they were queued under.
### How to Use
@@ -69,10 +68,8 @@ e.g.:
- If callers need an immediate flush action, `file_flush()` is the operational API.
- If a queued file sink still has pending records, callers should flush or close it first before changing auto-flush policy.
### Notes
1. Use this helper for runtime durability tuning.
2. On queued file sinks, clear pending records first so policy mutation does not retroactively affect already queued writes.
2. Pair it with `file_auto_flush()` to verify the active policy.
@@ -2,7 +2,7 @@
name: configured-logger-file-set-policy
group: api
category: runtime
update-time: 20260707
update-time: 20260512
description: Apply a bundled runtime file policy update to a configured file-backed logger.
key-word:
- logger
@@ -15,8 +15,6 @@ key-word:
Apply a bundled runtime file policy update to a `ConfiguredLogger`. This helper updates append mode, auto-flush, and rotation together through one runtime policy object.
The input `FileSinkPolicy` value is owned by `src/file_model`; this configured-logger surface is a facade over `Logger[@runtime.RuntimeSink]` and delegates policy mutation to the wrapped `RuntimeSink`.
### Interface
```moonbit
@@ -37,11 +35,9 @@ pub fn ConfiguredLogger::file_set_policy(self : ConfiguredLogger, policy : FileS
Detailed rules explaining key parameters and behaviors
- File-backed sinks update append, auto-flush, and rotation together through the wrapped `RuntimeSink`.
- Queued file sinks forward the policy update to the wrapped inner file sink only when no queued records are pending.
- The accepted policy object itself is the shared `@file_model.FileSinkPolicy` model, not a configured-logger-owned concrete type.
- Queued file sinks forward the policy update to the wrapped inner file sink.
- Non-file sinks return `false`.
- This helper is broader than the single-setting setters because it updates the whole file policy in one call.
- If a queued file sink still has pending records, the update is rejected and returns `false` so already queued records are not later written under a different policy bundle than the one they were queued under.
### How to Use
@@ -76,10 +72,8 @@ e.g.:
- If callers only need to change one setting, a narrower setter such as `file_set_auto_flush(...)` or `file_set_rotation(...)` may be clearer.
- If a queued file sink still has pending records, callers should flush or close it first before changing policy.
### Notes
1. Use this helper when the runtime policy should be treated as one cohesive object.
2. On queued file sinks, clear pending records first so policy mutation does not retroactively affect already queued writes.
2. It pairs naturally with `file_policy()` and `file_default_policy()`.
+36 -15
View File
@@ -2,8 +2,8 @@
name: configured-logger-file-set-rotation
group: api
category: runtime
update-time: 20260707
description: Update the rotation policy used by the configured runtime file sink.
update-time: 20260512
description: Update the rotation configuration used by the configured runtime file sink.
key-word:
- logger
- runtime
@@ -13,20 +13,21 @@ key-word:
## Configured-logger-file-set-rotation
Update the rotation policy used by a `ConfiguredLogger` file sink.
The input `FileRotation` value is owned by `src/file_model`; this configured-logger surface is a facade over `Logger[@runtime.RuntimeSink]` and delegates rotation mutation to the wrapped `RuntimeSink`.
Update the rotation configuration used by a `ConfiguredLogger` file sink. This helper changes runtime file rotation behavior without rebuilding the logger.
### Interface
```moonbit
pub fn ConfiguredLogger::file_set_rotation(self : ConfiguredLogger, rotation : FileRotation?) -> Bool {}
pub fn ConfiguredLogger::file_set_rotation(
self : ConfiguredLogger,
rotation : FileRotation?,
) -> Bool {}
```
#### input
- `self : ConfiguredLogger` - Config-driven runtime logger whose file rotation policy should change.
- `rotation : FileRotation?` - New runtime rotation policy.
- `self : ConfiguredLogger` - Config-driven runtime logger whose rotation policy should change.
- `rotation : FileRotation?` - New rotation config, or `None` to disable rotation.
#### output
@@ -37,21 +38,41 @@ pub fn ConfiguredLogger::file_set_rotation(self : ConfiguredLogger, rotation : F
Detailed rules explaining key parameters and behaviors
- File-backed sinks update their runtime rotation policy through the wrapped `RuntimeSink`.
- Queued file sinks forward the update to the wrapped inner file sink only when no queued records are pending.
- The accepted rotation object itself is the shared `@file_model.FileRotation` model, not a configured-logger-owned concrete type.
- Queued file sinks forward the update to the wrapped inner file sink.
- Passing `None` disables rotation.
- Non-file sinks return `false`.
- This helper changes policy only; it does not itself rotate or flush pending data.
- If a queued file sink still has pending records, the update is rejected and returns `false` so already queued records are not later written under a different rotation policy than the one they were queued under.
### How to Use
Here are some specific examples provided.
#### When Need Runtime Rotation Tuning
When a file sink should enable or change rotation dynamically:
```moonbit
ignore(logger.file_set_rotation(Some(file_rotation(1024, max_backups=3))))
```
In this example, runtime rotation behavior is updated without rebuilding the logger.
#### When Need To Disable Rotation
When the file sink should stop rotating:
```moonbit
let ok = logger.file_set_rotation(None)
```
In this example, the runtime file sink has its rotation policy cleared explicitly.
### Error Case
e.g.:
- If the configured sink is not file-backed, the method returns `false`.
- If a queued file sink still has pending records, callers should flush or close it first before changing rotation policy.
- If callers only want to remove rotation, `file_clear_rotation()` is the more direct API.
### Notes
1. Use this helper when runtime rotation policy should change without rebuilding the logger.
1. Use this helper when setting a full runtime rotation config.
2. On queued file sinks, clear pending records first so policy mutation does not retroactively affect already queued writes.
2. It is useful for operational tuning without rebuilding the logger.
@@ -1,79 +0,0 @@
---
name: configured-logger-file-state-or-none
group: api
category: runtime
update-time: 20260707
description: Read the current file sink snapshot from a ConfiguredLogger only when it is actually file-backed.
key-word:
- logger
- runtime
- file
- truthful
---
## Configured-logger-file-state-or-none
Read the current file sink snapshot from a `ConfiguredLogger` only when it is actually file-backed.
This is the truthful companion to `file_state()`. Prefer it when diagnostics or recovery logic must not confuse fallback snapshots with real file state.
### Interface
```moonbit
pub fn ConfiguredLogger::file_state_or_none(self : ConfiguredLogger) -> FileSinkState? {}
```
#### input
- `self : ConfiguredLogger` - Config-driven runtime logger whose file state snapshot should be inspected.
#### output
- `FileSinkState?` - `Some(snapshot)` when the configured sink is file-backed, otherwise `None`.
### Explanation
Detailed rules explaining key parameters and behaviors
- File-backed sinks return `Some(live_snapshot)` through the wrapped `RuntimeSink`.
- Queued file sinks forward the wrapped inner file sink snapshot as `Some(live_snapshot)`.
- Non-file sinks return `None`.
- This helper is broader than individual counters or policy reads because it returns the aggregated file snapshot without fallback synthesis.
### How to Use
Here are some specific examples provided.
#### When Need Truthful File Health Diagnostics
When support output should include file state only for real file-backed sinks:
```moonbit
match logger.file_state_or_none() {
Some(state) => println(stringify_file_sink_state(state, pretty=true))
None => ()
}
```
In this example, no compatibility snapshot is fabricated for non-file sinks.
#### When Need State Without Queue Expansion
When code only needs the file snapshot and not queue metadata:
```moonbit
let maybe_state = logger.file_state_or_none()
```
In this example, `None` cleanly signals missing file semantics.
### Error Case
e.g.:
- If the configured sink is not file-backed, the method returns `None`.
- If callers also need queue metrics for queued file sinks, prefer `file_runtime_state()`.
### Notes
1. Prefer this helper over `file_state()` for truthful runtime diagnostics.
2. `file_state()` remains available as the compatibility fallback API.
+3 -12
View File
@@ -2,8 +2,8 @@
name: configured-logger-file-state
group: api
category: runtime
update-time: 20260707
description: Read the current file sink snapshot from a configured runtime logger, with a compatibility fallback for non-file sinks.
update-time: 20260512
description: Read the current file sink snapshot from a configured runtime logger.
key-word:
- logger
- runtime
@@ -15,10 +15,6 @@ key-word:
Read the current file sink snapshot from a `ConfiguredLogger`. This helper exposes path, availability, policy flags, rotation config, and failure counters as one object.
The returned `FileSinkState` value is owned by `src/file_model`; this configured-logger surface is a facade over `Logger[@runtime.RuntimeSink]` and delegates file-state reads to the wrapped `RuntimeSink`.
`file_state()` is the compatibility form. For truthful file-semantics detection, prefer `file_state_or_none()`.
### Interface
```moonbit
@@ -39,10 +35,7 @@ Detailed rules explaining key parameters and behaviors
- File-backed sinks return a live snapshot of file state.
- Queued file sinks forward the snapshot from the wrapped inner file sink.
- The returned snapshot object itself is the shared `@file_model.FileSinkState` model, not a configured-logger-owned concrete type.
- Non-file sinks return the same fallback empty-style state produced by `RuntimeSink::file_state()`, with an empty path, disabled policy flags, no rotation, and zeroed counters.
- This fallback keeps older callers source-compatible, but it is not a live file-backed snapshot.
- New diagnostic or recovery code should prefer `file_state_or_none()`.
- This helper is broader than individual file counters or policy accessors because it aggregates core file status into one read.
### How to Use
@@ -72,12 +65,10 @@ In this example, the configured logger snapshot can be exported directly through
e.g.:
- If the configured sink is not file-backed, the returned snapshot is a fallback empty-style state rather than a live file view.
- If callers need a truthful file-semantics check, use `file_state_or_none()`.
- If callers also need queue context for queued file sinks, `file_runtime_state()` is the richer API.
### Notes
1. Use this helper for the main one-shot file status snapshot.
2. Prefer `file_state_or_none()` or `file_runtime_state()` when broader truthful diagnostics are needed.
2. Prefer it over individual counters when broader file diagnostics are needed.
@@ -1,78 +0,0 @@
---
name: configured-logger-flush-progress
group: api
category: runtime
update-time: 20260707
description: Return a structured generic flush progress snapshot for a ConfiguredLogger through RuntimeSink without collapsing queue and plain-file fallback semantics into one Int.
key-word:
- logger
- runtime
- flush
- public
---
## Configured-logger-flush-progress
Return a structured generic flush progress snapshot for a `ConfiguredLogger`. This is the recommended configured runtime wrapper over `RuntimeSink::flush_progress(...)` when code wants truthful generic progress instead of the compatibility `Int` returned by `flush()`.
### Interface
```moonbit
pub fn ConfiguredLogger::flush_progress(self : ConfiguredLogger) -> RuntimeSinkProgress {}
```
#### input
- `self : ConfiguredLogger` - Config-driven runtime logger whose generic flush progress should be observed.
#### output
- `RuntimeSinkProgress` - Structured progress snapshot returned by the wrapped `RuntimeSink::flush_progress(...)` call.
### Explanation
Detailed rules explaining key parameters and behaviors
- This helper delegates directly to `self.sink.flush_progress()`.
- Queue-wrapped sinks report queue advancement through `queue_advanced_count`.
- Plain file sinks report the generic fallback flush step through `file_flush_step_count`.
- Plain console-style sinks return a zeroed snapshot.
- This helper is the configured-logger entry point for the truthful generic progress surface introduced alongside the older compatibility `flush()` path.
### How to Use
Here are some specific examples provided.
#### When Need Recommended Generic Flush Progress On A Config-built Logger
When config-built runtime code should inspect flush progress explicitly:
```moonbit
let progress = logger.flush_progress()
```
In this example, the configured runtime logger reports structured progress without collapsing runtime-shape semantics.
#### When Need To Branch On Queue-backed Versus Plain-file Generic Progress
When application code should keep the config-built facade but still distinguish progress meaning:
```moonbit
let progress = logger.flush_progress()
if progress.queue_backed {
println(progress.queue_advanced_count)
}
```
In this example, queue advancement remains explicit even though the logger was built from config.
### Error Case
e.g.:
- If the configured runtime sink shape has no flushable state, the snapshot simply reports zero counts.
- If callers need file-specific success semantics on a file-backed logger, `file_flush()` is the better API.
### Notes
1. Prefer `flush_progress()` over `flush()` in new configured-runtime code.
2. `flush()` is still available for compatibility with older code that expects one numeric count.
+14 -21
View File
@@ -2,8 +2,8 @@
name: configured-logger-flush
group: api
category: runtime
update-time: 20260707
description: Compatibility configured runtime flush helper that still returns one Int by collapsing generic queue progress and plain-file fallback steps.
update-time: 20260613
description: Flush a configured runtime logger and return how many queued or file-backed operations were advanced through RuntimeSink.
key-word:
- logger
- runtime
@@ -13,7 +13,7 @@ key-word:
## Configured-logger-flush
Flush a `ConfiguredLogger` and return one compatibility count. This helper is still available for older code, but new configured-runtime code should prefer `flush_progress()` because it exposes queue advancement and plain-file fallback steps separately.
Flush a `ConfiguredLogger` and return how much work was advanced. This is the configured logger wrapper over `RuntimeSink::flush(...)` for forcing queued or file-backed output to move forward after config-driven construction.
### Interface
@@ -27,17 +27,16 @@ pub fn ConfiguredLogger::flush(self : ConfiguredLogger) -> Int {}
#### output
- `Int` - Compatibility count returned by the wrapped `RuntimeSink::flush(...)` call.
- `Int` - Count returned by the wrapped `RuntimeSink::flush(...)` call.
### Explanation
Detailed rules explaining key parameters and behaviors
- This helper delegates directly to `self.sink.flush()`.
- Under the hood, `RuntimeSink::flush()` now rebuilds one compatibility count from `flush_progress()`.
- Queue-wrapped sinks still report queued-record consumption through that compatibility count.
- Plain file sinks still report the generic fallback flush step as `1` or `0`.
- Plain console-style sinks still return `0`.
- Queue-wrapped sinks forward to the concrete queue sink's `flush()` behavior.
- Plain file sinks call `FileSink::flush()` through `RuntimeSink` and convert the boolean result into `1` or `0`.
- Plain console-style sinks return `0` because they do not expose a meaningful buffered flush step here.
### How to Use
@@ -45,37 +44,31 @@ Here are some specific examples provided.
#### When Need Explicit Queue Progress
When older code already expects one numeric flush count from a config-built logger:
When config-built queue output should be advanced manually:
```moonbit
ignore(logger.flush())
```
In this example, the configured runtime logger is flushed without changing the legacy return shape.
In this example, the configured runtime logger is flushed without reaching into the sink directly.
#### When Need A Post-write Flush Barrier
When code only needs a coarse non-zero check and does not care which runtime dimension advanced:
When a service wants stronger delivery behavior after a burst of writes:
```moonbit
let flushed = logger.flush()
```
In this example, callers still get one compatibility count rather than a structured progress snapshot.
In this example, callers can observe how much work was advanced by the flush request.
### Error Case
e.g.:
- If the configured runtime sink shape has no flushable state, the method may simply return `0`.
- If callers need truthful generic progress semantics, `flush_progress()` is the better API.
- If callers need bounded manual draining rather than generic flush behavior, `drain_progress(...)` is usually the better API.
- If callers need file-specific success semantics on a file-backed logger, `file_flush()` is the better API.
- If callers need bounded manual draining rather than generic flush behavior, `drain(...)` is the better API.
### Notes
1. Treat this method as a compatibility helper for older numeric code.
1. Use this helper after config-driven logger construction when explicit runtime flushing matters.
2. Prefer `flush_progress()` in new configured-runtime code.
3. The exact return value depends on which `RuntimeSink` variant the configured logger owns.
2. The exact return value depends on which `RuntimeSink` variant the configured logger owns.
+2 -3
View File
@@ -2,7 +2,7 @@
name: configured-logger
group: api
category: runtime
update-time: 20260707
update-time: 20260613
description: Public configured runtime logger alias used for config-built sync logging with queue and file controls.
key-word:
- logger
@@ -33,8 +33,7 @@ Detailed rules explaining key parameters and behaviors
- It preserves normal logger methods such as `info(...)`, `warn(...)`, `error(...)`, and the other `Logger` APIs.
- Because it is `Logger[RuntimeSink]`, it also keeps ordinary logger composition and target behavior such as `with_target(...)`, `child(...)`, and per-call `log(..., target=...)` overrides.
- In particular, `log(..., target=...)` can override the target for one call, while severity helpers such as `info(...)`, `warn(...)`, and `error(...)` continue using the stored logger target unless code derives another logger first with `with_target(...)` or `child(...)`.
- It also exposes configured runtime helpers such as `flush_progress()`, `drain_progress()`, `flush()`, `drain()`, `pending_count()`, `dropped_count()`, and file-specific controls when the runtime sink supports them.
- `flush_progress()` and `drain_progress()` are the recommended truthful generic progress helpers, while `flush()` and `drain()` remain compatibility wrappers that collapse the structured result back into one `Int`.
- It also exposes configured runtime helpers such as `flush()`, `drain()`, `pending_count()`, `dropped_count()`, and file-specific controls when the runtime sink supports them.
- Because `ConfiguredLogger` is only an alias over `Logger[RuntimeSink]`, ordinary sync composition helpers such as `with_target(...)`, `child(...)`, `with_timestamp(...)`, `with_filter(...)`, and `with_patch(...)` keep the same visible runtime-sink logger line rather than stripping away the configured helper surface.
- In current direct builder coverage, derived configured loggers still preserve queue counters, drain or flush behavior, runtime sink variant choice, and file helper access instead of collapsing back to a narrower non-runtime shape.
- Builders such as `build_logger(...)` and `parse_and_build_logger(...)` return this alias as the main sync config-to-runtime result.
+6 -20
View File
@@ -13,12 +13,12 @@ key-word:
## File-rotation-config-to-json
Convert `FileRotation` into a `Json`. On the root `src` facade, this helper forwards to the concrete serializer owned by `src/file_model`.
Convert `FileRotation` into a `JsonValue`. This helper is the structured export path for file rotation policy when callers need machine-readable config data instead of a runtime policy object.
### Interface
```moonbit
pub fn file_rotation_config_to_json(config : FileRotation) -> Json {}
pub fn file_rotation_config_to_json(config : FileRotation) -> @json_parser.JsonValue {}
```
#### input
@@ -27,16 +27,14 @@ pub fn file_rotation_config_to_json(config : FileRotation) -> Json {}
#### output
- `Json` - Structured JSON representation of the rotation policy.
- `JsonValue` - Structured JSON representation of the rotation policy.
### Explanation
Detailed rules explaining key parameters and behaviors
- The output always includes `max_bytes` and `max_backups`.
- The root surface forwards to `@file_model.file_rotation_config_to_json(...)`, which is the real owner of this serialization logic.
- Both of those compatibility fields are exported as JSON numbers.
- If the policy carries a wide threshold from `file_rotation_i64(...)`, the output also includes `max_bytes_i64` as a JSON string for exact roundtrip transport.
- The output includes `max_bytes` and `max_backups`.
- Both numeric fields are exported as JSON numbers.
- This helper serializes the rotation config object itself rather than sink availability, failure counters, or file state.
- The same JSON shape is reused by `sink_config_to_json(...)`, file sink state export helpers, and larger logger config serialization paths.
@@ -63,16 +61,6 @@ let rotation_json = file_rotation_config_to_json(rotation)
In this example, callers can carry the nested rotation shape without exporting a full sink config.
#### When Need Exact Wide-threshold Roundtrip
When a native large-file policy should preserve the original `Int64` threshold in JSON:
```moonbit
let rotation = file_rotation_i64(4294967296L, max_backups=2)
let rotation_json = file_rotation_config_to_json(rotation)
```
In this example, the JSON value includes the compatibility `max_bytes` view plus `max_bytes_i64` as a string.
### Error Case
e.g.:
@@ -82,8 +70,6 @@ e.g.:
### Notes
1. Use this helper when downstream code expects `Json` rather than a typed `FileRotation` value.
1. Use this helper when downstream code expects `JsonValue` rather than a typed `FileRotation` value.
2. Pair it with `file_rotation(...)` when building rotation policy in code before export.
3. For `file_rotation_i64(...)`, treat `max_bytes_i64` as the exact roundtrip field and `max_bytes` as the compatibility view.
-74
View File
@@ -1,74 +0,0 @@
---
name: file-rotation-i64
group: api
category: sink
update-time: 20260705
description: Create a native-focused large-file rotation policy using an Int64 byte threshold.
key-word:
- file
- rotation
- i64
- native
---
## File-rotation-i64
Create a size-based file rotation policy with an `Int64` byte threshold. This helper is the opt-in native-focused path for large-file rotation scenarios that exceed the default `Int`-based contract.
### Interface
```moonbit
pub fn file_rotation_i64(max_bytes : Int64, max_backups~ : Int = 1) -> FileRotation {}
```
#### input
- `max_bytes : Int64` - Maximum active file size threshold before rotation on the native-focused wide path.
- `max_backups : Int` - Number of retained backup files.
#### output
- `FileRotation` - Rotation policy value that preserves a native wide threshold while staying compatible with the existing file sink API surface.
### Explanation
- `max_bytes <= 0L` is normalized to `1L`.
- `max_backups <= 0` is normalized to `1`.
- Rotation is size-based only.
- This helper keeps the existing `FileRotation` type but stores an additional native wide threshold internally for runtime rotation checks.
- The helper is intended for native file backends and advanced large-file scenarios.
- JSON config export helpers preserve the exact threshold through `max_bytes_i64` while still exposing a compatibility `max_bytes` view.
### How to Use
#### When Need Native Large-file Rotation Thresholds
```moonbit
let sink = file_sink(
"app.log",
rotation=Some(file_rotation_i64(5368709120L, max_backups=4)),
)
```
In this example, the active rotation threshold is expressed with `Int64` rather than the default `Int` path.
#### When Need A Wide Policy Value First
```moonbit
let rotation = file_rotation_i64(3221225472L, max_backups=2)
let sink = file_sink("app.log", rotation=Some(rotation))
```
In this example, the wide threshold policy is assembled separately and then reused.
### Error Case
- If `max_bytes` is non-positive, it is clamped to `1L`.
- This API does not make non-native targets gain real file support; callers should still use `native_files_supported()` when portability matters.
### Notes
1. This API is additive and does not replace the default `file_rotation(...)` contract.
2. Prefer the default `Int` path unless a native large-file threshold is actually required.
3. String-based JSON roundtrip uses `max_bytes_i64` for the exact threshold and keeps `max_bytes` as the compatibility field.
4. This helper is designed for advanced use and target-aware code.
+9 -13
View File
@@ -2,8 +2,8 @@
name: file-rotation-type
group: api
category: sink
update-time: 20260707
description: Public file rotation type re-exported from file_model for root file and config APIs.
update-time: 20260613
description: Public file rotation alias used for native size-based file sink policy data.
key-word:
- file
- rotation
@@ -13,28 +13,26 @@ key-word:
## File-rotation-type
`FileRotation` is the public file sink rotation policy type used for size-based log file rollover. On the root `src` facade, it is re-exported from `src/file_model`, which is the real owner of the concrete file rotation model.
`FileRotation` is the public file sink rotation policy type used for native size-based log file rollover. It is a direct alias to the sink model that stores the byte limit and retained backup count.
### Interface
```moonbit
pub using @file_model { type FileRotation }
pub type FileRotation = @utils.FileRotation
```
#### output
- `FileRotation` - Public file rotation policy object containing the standard `max_bytes` view, `max_backups`, and additive native wide-threshold support for advanced rotation flows.
- `FileRotation` - Public file rotation policy object containing `max_bytes` and `max_backups`.
### Explanation
Detailed rules explaining key parameters and behaviors
- This root surface is a re-export, not the concrete owner definition.
- The concrete type lives in `@file_model.FileRotation`, not in `@utils` and not in `@file_runtime`.
- The current fields are `max_bytes : Int`, `max_backups : Int`, and additive native wide-threshold metadata used by the optional `file_rotation_i64(...)` path.
- This is a type alias, not a file sink or rotation trigger by itself.
- The current fields are `max_bytes : Int` and `max_backups : Int`.
- `file_rotation(...)` constructs this type as the main public helper.
- The same value type is consumed by `file_sink(...)`, `FileSinkPolicy::new(...)`, `SinkConfig`, file runtime inspection APIs, and logger config serialization helpers.
- `file_runtime` owns the live `FileSink` behavior that consumes this type, while `runtime` owns higher-level runtime file projections.
### How to Use
@@ -67,8 +65,6 @@ e.g.:
### Notes
1. Use `file_rotation(...)` when you need the default `Int`-based value of this type in code.
1. Use `file_rotation(...)` when you need a value of this type in code.
2. Use `file_rotation_i64(...)` when a native large-file threshold must exceed the default `Int` contract.
3. Use `native_files_supported()` or the target verification guidance when portability matters across non-native targets.
2. Use `native_files_supported()` or the target verification guidance when portability matters across non-native targets.
-5
View File
@@ -38,9 +38,6 @@ Detailed rules explaining key parameters and behaviors
- `max_backups <= 0` is normalized to `1`.
- Rotation is size-based only.
- This policy is consumed by `file_sink(...)`, file policy helpers, and config-driven file sink assembly.
- The default `max_bytes : Int` path follows the current 32-bit `Int` contract used by the standard file rotation APIs.
- On native targets, that default path is intended for ordinary log-file ranges rather than explicit large-file guarantees beyond the 32-bit `Int` boundary.
- If a native large-file threshold is required, prefer `file_rotation_i64(...)`.
### How to Use
@@ -82,5 +79,3 @@ e.g.:
2. Rotation currently focuses on size thresholds rather than time schedules or compression.
3. The default API keeps the portable `Int`-based contract stable; the wider native-only path is exposed separately through `file_rotation_i64(...)`.
+4 -8
View File
@@ -13,12 +13,12 @@ key-word:
## File-sink-policy-to-json
Convert `FileSinkPolicy` into a `Json`. On the root `src` facade, this helper forwards to the concrete serializer owned by `src/file_model`.
Convert `FileSinkPolicy` into a `JsonValue`. This helper exports append mode, auto-flush, and optional rotation as a structured runtime policy snapshot.
### Interface
```moonbit
pub fn file_sink_policy_to_json(policy : FileSinkPolicy) -> Json {}
pub fn file_sink_policy_to_json(policy : FileSinkPolicy) -> @json_parser.JsonValue {}
```
#### input
@@ -27,19 +27,17 @@ pub fn file_sink_policy_to_json(policy : FileSinkPolicy) -> Json {}
#### output
- `Json` - Structured JSON representation of the file policy.
- `JsonValue` - Structured JSON representation of the file policy.
### Explanation
Detailed rules explaining key parameters and behaviors
- The output includes `append`, `auto_flush`, and `rotation`.
- The root surface forwards to `@file_model.file_sink_policy_to_json(...)`, which is the real owner of this serialization logic.
- `rotation` is exported as `null` when rotation is disabled.
- This helper exports runtime file policy, not current file health counters or availability.
- The JSON value is useful for policy snapshots, comparisons, and diagnostics payloads.
- Typical inputs come from `FileSink::policy()`, `RuntimeSink::file_policy()`, or `ConfiguredLogger::file_policy()`.
- If the active rotation policy originated from `file_rotation_i64(...)`, the nested rotation JSON includes both the compatibility `max_bytes` number and `max_bytes_i64` as the exact string form.
### How to Use
@@ -73,8 +71,6 @@ e.g.:
### Notes
1. Use this helper when downstream code expects `Json` rather than text.
1. Use this helper when downstream code expects `JsonValue` rather than text.
2. It pairs naturally with `FileSink::policy()`, `RuntimeSink::file_policy()`, and related default-policy accessors.
3. For wide native rotation policies, downstream code should read `rotation.max_bytes_i64` when exact threshold recovery matters.
+5 -6
View File
@@ -2,8 +2,8 @@
name: file-sink-policy
group: api
category: sink
update-time: 20260707
description: Public file policy type re-exported from file_model for file and runtime control APIs.
update-time: 20260613
description: Public file policy alias used by file sinks and runtime file-control APIs.
key-word:
- file
- policy
@@ -13,12 +13,12 @@ key-word:
## File-sink-policy
`FileSinkPolicy` is the public policy object used to describe file append mode, auto-flush behavior, and optional rotation settings together. On the root `src` facade, it is re-exported from `src/file_model`, which is the real owner of the concrete policy model.
`FileSinkPolicy` is the public policy object used to describe file append mode, auto-flush behavior, and optional rotation settings together. It is a direct alias to the file policy model shared by `FileSink`, `RuntimeSink`, `ConfiguredLogger`, and file policy JSON helpers.
### Interface
```moonbit
pub using @file_model { type FileSinkPolicy }
pub type FileSinkPolicy = @utils.FileSinkPolicy
```
#### output
@@ -29,8 +29,7 @@ pub using @file_model { type FileSinkPolicy }
Detailed rules explaining key parameters and behaviors
- This root surface is a re-export, not the concrete owner definition.
- The concrete type lives in `@file_model.FileSinkPolicy`, not in `@utils`.
- This is a type alias, not a separate runtime wrapper.
- The current policy fields are `append : Bool`, `auto_flush : Bool`, and `rotation : FileRotation?`.
- The same policy object is returned by `FileSink::policy()`, `RuntimeSink::file_policy()`, and `ConfiguredLogger::file_policy()`.
- It is also accepted by `FileSink::set_policy(...)`, `RuntimeSink::file_set_policy(...)`, and `ConfiguredLogger::file_set_policy(...)`.
+1 -2
View File
@@ -2,7 +2,7 @@
name: file-sink-reopen-append
group: api
category: sink
update-time: 20260717
update-time: 20260613
description: Reopen a FileSink in append mode.
key-word:
- file
@@ -37,7 +37,6 @@ Detailed rules explaining key parameters and behaviors
- Reopen behavior is fixed to append mode.
- The stored append policy is updated to `true` as part of the reopen path.
- On failure, the sink remains unavailable and `open_failures` is incremented.
- After a rotation failure, this is the explicit recovery path once the underlying remove, rename, or open condition has been resolved.
### How to Use
+5 -12
View File
@@ -2,7 +2,7 @@
name: file-sink-rotation-failures
group: api
category: sink
update-time: 20260717
update-time: 20260613
description: Read the number of rotation failures recorded by a FileSink.
key-word:
- file
@@ -13,7 +13,7 @@ key-word:
## File-sink-rotation-failures
Read the number of rotation attempts whose critical file-rotation steps failed for a `FileSink`.
Read the number of rotation failures recorded by a `FileSink`. This helper is useful when direct runtime rotation behavior should be observed operationally.
### Interface
@@ -34,9 +34,6 @@ pub fn FileSink::rotation_failures(self : FileSink) -> Int {
Detailed rules explaining key parameters and behaviors
- The sink reports its recorded rotation-failure count directly.
- The counter increases when a rotation attempt cannot complete its critical file steps, such as removing the active file with zero backups, renaming a live file into `.1`, shifting an existing backup to a higher slot, or reopening the fresh active file afterward.
- Missing optional backup slots do not count by themselves; only steps that fail while their source path still exists are treated as rotation failures.
- When a critical rotation step fails, the triggering record is not written and the sink remains unavailable until an explicit reopen succeeds.
- The counter is cumulative until reset.
- This helper is observation-only and does not mutate sink state.
@@ -51,7 +48,7 @@ When support output should reveal whether direct sink rotation is failing:
let count = sink.rotation_failures()
```
In this example, the concrete file sink exposes whether a rotation attempt hit a critical file-step failure.
In this example, the concrete file sink exposes a focused metric for rotation-path health.
#### When Validate Runtime Rotation Tuning
@@ -60,21 +57,17 @@ When changed rotation settings should be checked in operation:
ignore(sink.rotation_failures())
```
In this example, callers can observe whether runtime rotation changes started producing incomplete rotations.
In this example, callers can observe whether runtime rotation changes introduced problems.
### Error Case
e.g.:
- If callers need both rotation config and failure metrics, they should combine this helper with `rotation_config()` or `state()`.
- This counter alone does not identify which rename/remove/reopen step failed.
- This counter alone does not say whether the sink is currently available.
- After a recorded rotation failure, use `reopen_append()` only after the underlying filesystem condition has been resolved.
### Notes
1. Use this helper when diagnosing incomplete direct file rotations.
1. Use this helper when diagnosing direct file rotation reliability.
2. It is especially relevant when runtime rotation policy can change after startup.
+4 -8
View File
@@ -13,12 +13,12 @@ key-word:
## File-sink-state-to-json
Convert `FileSinkState` into a `Json`. On the root `src` facade, this helper forwards to the concrete serializer owned by `src/file_model`.
Convert `FileSinkState` into a `JsonValue`. This helper exports file path, availability, policy flags, rotation config, and failure counters in a structured form.
### Interface
```moonbit
pub fn file_sink_state_to_json(state : FileSinkState) -> Json {}
pub fn file_sink_state_to_json(state : FileSinkState) -> @json_parser.JsonValue {}
```
#### input
@@ -27,19 +27,17 @@ pub fn file_sink_state_to_json(state : FileSinkState) -> Json {}
#### output
- `Json` - Structured JSON representation of the file sink state.
- `JsonValue` - Structured JSON representation of the file sink state.
### Explanation
Detailed rules explaining key parameters and behaviors
- The output includes `path`, `available`, `append`, `auto_flush`, failure counters, and `rotation`.
- The root surface forwards to `@file_model.file_sink_state_to_json(...)`, which is the real owner of this serialization logic.
- `rotation` is exported as `null` when rotation is disabled.
- This helper exports state snapshots, not mutable runtime control handles.
- It is useful when file sink state should be embedded into larger diagnostics payloads.
- Typical inputs come from `FileSink::state()`, `RuntimeSink::file_state()`, or `ConfiguredLogger::file_state()`.
- If the live rotation policy was created from `file_rotation_i64(...)`, the nested `rotation` JSON includes `max_bytes_i64` as a string alongside the compatibility `max_bytes` number.
### How to Use
@@ -72,8 +70,6 @@ e.g.:
### Notes
1. Use this helper when diagnostics consumers expect `Json`.
1. Use this helper when diagnostics consumers expect `JsonValue`.
2. It pairs naturally with `FileSink::state()`, `RuntimeSink::file_state()`, and `ConfiguredLogger::file_state()`.
3. For wide native rotation policies, `rotation.max_bytes_i64` is the exact roundtrip field.
+5 -7
View File
@@ -2,8 +2,8 @@
name: file-sink-state
group: api
category: runtime
update-time: 20260707
description: Public file state type re-exported from file_model for live file-sink snapshots and runtime diagnostics.
update-time: 20260613
description: Public file state alias used for live file-sink snapshots and runtime diagnostics.
key-word:
- file
- state
@@ -13,12 +13,12 @@ key-word:
## File-sink-state
`FileSinkState` is the public snapshot object used to describe the current state of a file sink. On the root `src` facade, it is re-exported from `src/file_model`, which is the real owner of the concrete file state model.
`FileSinkState` is the public snapshot object used to describe the current state of a file sink. It is a direct alias to the file state model returned by `FileSink::state()` and by higher-level runtime file inspection helpers.
### Interface
```moonbit
pub using @file_model { type FileSinkState }
pub type FileSinkState = @utils.FileSinkState
```
#### output
@@ -29,10 +29,8 @@ pub using @file_model { type FileSinkState }
Detailed rules explaining key parameters and behaviors
- This root surface is a re-export, not the concrete owner definition.
- The concrete type lives in `@file_model.FileSinkState`, not in `@utils`.
- This is a type alias, not a live file handle wrapper.
- The current snapshot fields are `path`, `available`, `append`, `auto_flush`, `rotation`, `open_failures`, `write_failures`, `flush_failures`, and `rotation_failures`.
- `rotation_failures` records how many rotation attempts failed to complete critical remove/rename/reopen steps; it is not a full file-health or backup-integrity audit.
- `FileSink::state()` returns this object directly for a concrete file sink.
- `RuntimeSink::file_state()` also returns this type, including fallback snapshots for non-file runtime sinks.
- `ConfiguredLogger::file_state()` returns the same snapshot type through the config-built runtime wrapper.
+20 -7
View File
@@ -2,8 +2,8 @@
name: file-sink-type
group: api
category: sink
update-time: 20260707
description: Public file sink type re-exported from file_runtime for file-backed synchronous logging.
update-time: 20260613
description: Public native file sink type used for file-backed synchronous logging with runtime policy and failure tracking.
key-word:
- sink
- file
@@ -13,12 +13,26 @@ key-word:
## File-sink-type
`FileSink` is the public file sink type used for file-backed synchronous logging. On the root `src` facade, it is re-exported from `src/file_runtime`, which is the real owner of the concrete sink behavior type.
`FileSink` is the public native file sink type used for file-backed synchronous logging. It is the concrete sink type returned by `file_sink(...)`, and it stores runtime file policy, availability state, formatter behavior, and failure counters.
### Interface
```moonbit
pub using @file_runtime { type FileSink }
pub struct FileSink {
path : String
append : Ref[Bool]
default_append : Bool
handle : Ref[FileHandle?]
formatter : RecordFormatter
auto_flush : Ref[Bool]
default_auto_flush : Bool
rotation : Ref[FileRotation?]
default_rotation : FileRotation?
open_failures : Ref[Int]
write_failures : Ref[Int]
flush_failures : Ref[Int]
rotation_failures : Ref[Int]
}
```
#### output
@@ -29,9 +43,8 @@ pub using @file_runtime { type FileSink }
Detailed rules explaining key parameters and behaviors
- This root surface is a re-export of the concrete `@file_runtime.FileSink` type.
- The struct intentionally hides its fields; callers interact through methods such as `flush()`, `close()`, `reopen()`, `policy()`, and `state()`.
- File model companions such as `FileRotation`, `FileSinkPolicy`, `FileSinkState`, and `RuntimeFileState` are owned by `@file_model`, not by `FileSink` itself.
- This is a public root struct, not a type alias.
- The current fields cover path, append mode, handle state, formatter, auto-flush policy, optional rotation policy, and failure counters.
- `file_sink(...)` constructs this type directly from path and policy inputs.
- The type exposes runtime helpers such as `flush()`, `close()`, `reopen()`, `policy()`, `state()`, and failure-counter accessors.
+2 -4
View File
@@ -13,7 +13,7 @@ key-word:
## File-sink
Create a native file sink for text-oriented or custom-formatted file logging. On the root `src` facade, this helper forwards to `src/file_runtime`, while the companion file model types it accepts and returns are owned by `src/file_model`.
Create a native file sink for text-oriented or custom-formatted file logging. This API includes lifecycle controls, rotation configuration, reopen behavior, policy inspection, and failure counters.
### Interface
@@ -32,7 +32,7 @@ pub fn file_sink(
- `path : String` - Destination file path.
- `append : Bool` - Whether opening/reopening should append rather than truncate.
- `auto_flush : Bool` - Whether flush is attempted after each write.
- `rotation : FileRotation?` - Optional size-based rotation policy. The default helper path is `file_rotation(...)`; advanced native large-file callers can also pass a policy created by `file_rotation_i64(...)`.
- `rotation : FileRotation?` - Optional size-based rotation policy.
- `formatter : RecordFormatter` - Formatter used to render each record before writing.
#### output
@@ -44,8 +44,6 @@ pub fn file_sink(
Detailed rules explaining key parameters and behaviors
- This sink is designed for host-file capable backends, with current local verification centered on `native`.
- The root `file_sink(...)` entry is a facade over `@file_runtime.file_sink(...)`.
- The accepted `FileRotation` input and the related `FileSinkPolicy` / `FileSinkState` diagnostics types come from `@file_model`.
- `llvm` should be treated as experimental in the current release context and was not successfully re-verified in this environment.
- The `src` library is still designed for multi-target compilation, but file sink availability remains backend-sensitive inside that broader portable surface.
- `append` is persistent policy state and also affects later reopen behavior.
+2 -6
View File
@@ -13,9 +13,7 @@ key-word:
## File
Create a `LoggerConfig` preset for the built-in file sink. On the root `src` facade, this helper forwards to the preset builder owned by `src/presets_pkg` and returns a `LoggerConfig` owned by `src/config_model`.
The optional `rotation` value accepted here is the shared `FileRotation` model owned by `src/file_model`.
Create a `LoggerConfig` preset for the built-in file sink. This helper packages file path, append policy, auto-flush behavior, optional rotation, and text formatter settings into a single config object for runtime logger assembly.
### Interface
@@ -40,7 +38,7 @@ pub fn file(
- `timestamp : Bool` - Whether the built logger should emit timestamps.
- `append : Bool` - Whether file writes should append instead of truncate-on-open behavior.
- `auto_flush : Bool` - Whether writes should be flushed automatically.
- `rotation : FileRotation?` - Optional size-based file rotation policy. The default `file_rotation(...)` path uses the standard `Int`-based threshold contract, while advanced native large-file callers can opt into `file_rotation_i64(...)`.
- `rotation : FileRotation?` - Optional size-based file rotation policy.
- `text_formatter : TextFormatterConfig` - Formatter config used for file text rendering.
#### output
@@ -52,8 +50,6 @@ pub fn file(
Detailed rules explaining key parameters and behaviors
- This preset always returns `sink.kind=SinkKind::File`.
- The root `file(...)` entry is a facade over `@presets_pkg.file(...)`.
- The returned config shape is the shared `@config_model.LoggerConfig` / `@config_model.SinkConfig` model, not a preset-owned concrete type.
- `path` must be non-empty.
- `rotation=None` leaves file rotation disabled until a rotation policy is provided directly or through `with_file_rotation(...)`.
- `queue=None` by default, so buffering is opt-in through `with_queue(...)`.
-18
View File
@@ -31,7 +31,6 @@ BitLogger API navigation.
- [logger-with-timestamp.md](./logger-with-timestamp.md)
- [logger-with-context-fields.md](./logger-with-context-fields.md)
- [logger-bind.md](./logger-bind.md)
- [logger-with-trace-context.md](./logger-with-trace-context.md)
- [logger-with-filter.md](./logger-with-filter.md)
- [logger-with-patch.md](./logger-with-patch.md)
- [logger-with-queue.md](./logger-with-queue.md)
@@ -100,10 +99,6 @@ BitLogger API navigation.
- [fields.md](./fields.md)
- [text-formatter-config-type.md](./text-formatter-config-type.md)
## Observability
- [trace-context.md](./trace-context.md)
## Record and level
- [record.md](./record.md)
@@ -183,7 +178,6 @@ BitLogger API navigation.
- [file-sink-type.md](./file-sink-type.md)
- [native-files-supported.md](./native-files-supported.md)
- [file-rotation.md](./file-rotation.md)
- [file-rotation-i64.md](./file-rotation-i64.md)
- [file-rotation-type.md](./file-rotation-type.md)
- [file-sink-policy-to-json.md](./file-sink-policy-to-json.md)
- [file-sink-policy.md](./file-sink-policy.md)
@@ -250,7 +244,6 @@ BitLogger API navigation.
- [file.md](./file.md)
- [with-queue.md](./with-queue.md)
- [with-file-rotation.md](./with-file-rotation.md)
- [with-file-rotation-i64.md](./with-file-rotation-i64.md)
## Async logger
@@ -271,7 +264,6 @@ BitLogger API navigation.
- [async-logger-with-min-level.md](./async-logger-with-min-level.md)
- [async-logger-with-timestamp.md](./async-logger-with-timestamp.md)
- [async-logger-with-context-fields.md](./async-logger-with-context-fields.md)
- [async-logger-with-trace-context.md](./async-logger-with-trace-context.md)
- [async-logger-with-filter.md](./async-logger-with-filter.md)
- [async-logger-with-patch.md](./async-logger-with-patch.md)
@@ -328,7 +320,6 @@ BitLogger API navigation.
- [library-logger-child.md](./library-logger-child.md)
- [library-logger-with-context-fields.md](./library-logger-with-context-fields.md)
- [library-logger-bind.md](./library-logger-bind.md)
- [library-logger-with-trace-context.md](./library-logger-with-trace-context.md)
- [library-logger-is-enabled.md](./library-logger-is-enabled.md)
- [library-logger-log.md](./library-logger-log.md)
- [library-logger-info.md](./library-logger-info.md)
@@ -348,7 +339,6 @@ BitLogger API navigation.
- [library-async-logger-child.md](./library-async-logger-child.md)
- [library-async-logger-with-context-fields.md](./library-async-logger-with-context-fields.md)
- [library-async-logger-bind.md](./library-async-logger-bind.md)
- [library-async-logger-with-trace-context.md](./library-async-logger-with-trace-context.md)
- [library-async-logger-is-enabled.md](./library-async-logger-is-enabled.md)
- [library-async-logger-log.md](./library-async-logger-log.md)
- [library-async-logger-info.md](./library-async-logger-info.md)
@@ -374,7 +364,6 @@ BitLogger API navigation.
- [runtime-sink-pending-count.md](./runtime-sink-pending-count.md)
- [runtime-sink-dropped-count.md](./runtime-sink-dropped-count.md)
- [runtime-sink-file-path.md](./runtime-sink-file-path.md)
- [runtime-sink-file-path-or-none.md](./runtime-sink-file-path-or-none.md)
- [runtime-sink-file-available.md](./runtime-sink-file-available.md)
- [runtime-sink-file-reopen.md](./runtime-sink-file-reopen.md)
- [runtime-sink-file-reopen-with-current-policy.md](./runtime-sink-file-reopen-with-current-policy.md)
@@ -398,12 +387,9 @@ BitLogger API navigation.
- [runtime-sink-file-reset-failure-counters.md](./runtime-sink-file-reset-failure-counters.md)
- [runtime-sink-file-reset-policy.md](./runtime-sink-file-reset-policy.md)
- [runtime-sink-file-policy.md](./runtime-sink-file-policy.md)
- [runtime-sink-file-policy-or-none.md](./runtime-sink-file-policy-or-none.md)
- [runtime-sink-file-default-policy.md](./runtime-sink-file-default-policy.md)
- [runtime-sink-file-default-policy-or-none.md](./runtime-sink-file-default-policy-or-none.md)
- [runtime-sink-file-policy-matches-default.md](./runtime-sink-file-policy-matches-default.md)
- [runtime-sink-file-state.md](./runtime-sink-file-state.md)
- [runtime-sink-file-state-or-none.md](./runtime-sink-file-state-or-none.md)
- [runtime-sink-file-runtime-state.md](./runtime-sink-file-runtime-state.md)
- [configured-logger.md](./configured-logger.md)
- [configured-logger-flush.md](./configured-logger-flush.md)
@@ -416,14 +402,10 @@ BitLogger API navigation.
- [configured-logger-file-available.md](./configured-logger-file-available.md)
- [configured-logger-file-path.md](./configured-logger-file-path.md)
- [configured-logger-file-path-or-none.md](./configured-logger-file-path-or-none.md)
- [configured-logger-file-state.md](./configured-logger-file-state.md)
- [configured-logger-file-state-or-none.md](./configured-logger-file-state-or-none.md)
- [configured-logger-file-runtime-state.md](./configured-logger-file-runtime-state.md)
- [configured-logger-file-policy.md](./configured-logger-file-policy.md)
- [configured-logger-file-policy-or-none.md](./configured-logger-file-policy-or-none.md)
- [configured-logger-file-default-policy.md](./configured-logger-file-default-policy.md)
- [configured-logger-file-default-policy-or-none.md](./configured-logger-file-default-policy-or-none.md)
- [configured-logger-file-policy-matches-default.md](./configured-logger-file-policy-matches-default.md)
- [configured-logger-file-rotation-config.md](./configured-logger-file-rotation-config.md)
- [configured-logger-file-rotation-enabled.md](./configured-logger-file-rotation-enabled.md)
+4 -4
View File
@@ -2,7 +2,7 @@
name: library-async-logger-new
group: api
category: facade
update-time: 20260707
update-time: 20260613
description: Create a narrower library-facing async logger facade by building a regular async logger and wrapping the same underlying state.
key-word:
- async
@@ -23,7 +23,7 @@ pub fn[S] LibraryAsyncLogger::new(
config~ : AsyncLoggerConfig = AsyncLoggerConfig::new(),
min_level~ : @bitlogger.Level = @bitlogger.Level::Info,
target~ : String = "",
flush~ : (S) -> Unit raise = fn(_) { () },
flush~ : (S) -> Int raise = fn(_) { 0 },
) -> LibraryAsyncLogger[S] {
```
@@ -33,7 +33,7 @@ pub fn[S] LibraryAsyncLogger::new(
- `config : AsyncLoggerConfig` - Queue size, overflow behavior, batching, linger, and flush policy.
- `min_level : Level` - Minimum enabled level. Messages below this threshold are ignored before enqueue.
- `target : String` - Default target attached to emitted records unless later overridden.
- `flush : (S) -> Unit raise` - Flush callback used when async batch or shutdown policy needs explicit flushing, and allowed to raise if flushing fails.
- `flush : (S) -> Int raise` - Flush callback used when async batch or shutdown policy needs explicit flushing, and allowed to raise if flushing fails.
#### output
@@ -73,7 +73,7 @@ When the sink requires a flush callback for batch or shutdown policy:
```moonbit
let logger = LibraryAsyncLogger::new(
@bitlogger.console_sink(),
flush=fn(sink) { () },
flush=fn(sink) { 0 },
)
```
+1 -3
View File
@@ -2,7 +2,7 @@
name: library-async-logger-run
group: api
category: facade
update-time: 20260707
update-time: 20260613
description: Start the LibraryAsyncLogger worker loop by delegating to the wrapped async logger's run behavior.
key-word:
- async
@@ -35,7 +35,6 @@ Detailed rules explaining key parameters and behaviors
- This method delegates directly to the wrapped async logger's `run()` behavior.
- It starts the worker loop that makes accepted queued records reach the underlying sink.
- The delegated `run()` call now preserves the wrapped logger's single-worker guard, so a second concurrent facade-level startup raises `AsyncLoggerAlreadyRunning`.
- Failure and lifecycle state are still tracked by the wrapped async logger.
- Once a delegated `run()` call has actually started, it clears any previous `has_failed()` flag and stored `last_error()` string on that same wrapped logger before draining resumes.
- The narrower library facade does not hide the need to explicitly activate queue draining.
@@ -79,7 +78,6 @@ e.g.:
- If `run()` is never started, accepted records may remain queued and not reach the sink.
- A later delegated `run()` attempt starts from a fresh failure flag and empty `last_error()` string on the same wrapped logger, even if an earlier facade-level run failed.
- A concurrent delegated `run()` attempt while the wrapped logger is already active fails explicitly with `AsyncLoggerAlreadyRunning`.
- If callers need to inspect `is_running()`, `has_failed()`, or `last_error()` directly, they must unwrap first with `to_async_logger()`.
+10 -7
View File
@@ -2,8 +2,8 @@
name: library-async-logger-shutdown
group: api
category: facade
update-time: 20260707
description: Gracefully stop a LibraryAsyncLogger by delegating to the wrapped async logger's shutdown behavior, including drain and worker-wait rules.
update-time: 20260614
description: Gracefully stop a LibraryAsyncLogger by delegating to the wrapped async logger's shutdown behavior, including runtime-dependent drain and worker-wait rules.
key-word:
- async
- library
@@ -39,12 +39,13 @@ Detailed rules explaining key parameters and behaviors
- This method delegates directly to the wrapped async logger's `shutdown(...)` behavior.
- `clear=false` first waits for idle, then closes the logger.
- If backlog still remains after `wait_idle()` because failure stopped progress early, the wrapped logger falls back to `close(clear=true)`.
- If the active async runtime uses shutdown clearing after idle and backlog still remains, the wrapped logger falls back to `close(clear=true)`.
- `clear=true` immediately closes and abandons pending records, even if the facade never started a drain worker for the wrapped logger.
- The method then waits until the worker is no longer running before returning.
- After a worker-failure short-circuit, delegated shutdown converts remaining backlog into dropped records before it returns.
- In runtimes where shutdown waits for workers, the method then waits until the worker is no longer running before returning.
- After a worker-failure short-circuit, native-worker backends can still convert remaining backlog into dropped records, while compatibility backends skip that extra forced-clear step.
- In the current direct facade coverage, the wrapped logger ends that path with `pending_count() == 0` and one more dropped item on native-worker runtimes, versus a still-nonzero pending count and no extra dropped cleanup on compatibility runtimes.
- Delegated shutdown also does not clear retained worker failure state by itself. If the wrapped logger had already recorded a worker error, later inspection through `to_async_logger()` can still show `has_failed=true` and the same `last_error()` string after shutdown completes.
- The narrower library facade does not change any of these shutdown rules; it only keeps the broader inspection helpers out of the direct public surface.
- The narrower library facade does not change any of these runtime-dependent shutdown rules; it only keeps the broader inspection helpers out of the direct public surface.
- Inspecting the logger later through `to_async_logger()` reveals the same delegated shutdown result rather than a rebuilt or translated lifecycle snapshot.
### How to Use
@@ -78,6 +79,8 @@ e.g.:
- `clear=true` can therefore be used as the facade-level no-worker cleanup path when queued records were accepted but no `run()` task was ever started.
- In compatibility-style runtimes without background-worker waiting, shutdown still closes the logger but may not perform the extra wait-for-worker phase described for native-worker runtimes.
- Even when delegated shutdown finishes with `is_closed=true`, callers can still observe retained `has_failed()` and `last_error()` on the unwrapped logger if the worker had already failed before shutdown cleanup completed.
- If callers skip `shutdown()` and only inspect flags manually, it is easier to leave the worker lifecycle in an unclear state.
@@ -88,7 +91,7 @@ e.g.:
1. Prefer this API over low-level closure control in normal library shutdown paths.
2. Delegated shutdown waits for an already-running worker to finish before returning.
2. Exact post-close waiting behavior depends on the active async runtime mode.
3. Choose `clear=true` only when loss of queued records is acceptable.
@@ -2,7 +2,7 @@
name: library-async-logger-to-async-logger
group: api
category: facade
update-time: 20260707
update-time: 20260614
description: Recover the underlying full async logger from the library-facing async facade without rebuilding, copying, or detaching the wrapped async state.
key-word:
- async
@@ -40,9 +40,9 @@ Detailed rules explaining key parameters and behaviors
- Use this when code needs wider async logger APIs outside the library facade.
- This is the step required for helpers such as `pending_count()`, `dropped_count()`, `state()`, `wait_idle()`, `has_failed()`, `last_error()`, or broader composition methods that are intentionally hidden by `LibraryAsyncLogger[S]`.
- It is also the step that exposes the real post-run or post-shutdown state after facade-level lifecycle calls, because those calls delegated to this same wrapped logger all along.
- That includes failure/backlog combinations and shutdown results exactly as they accumulated behind the facade.
- That includes failure/backlog combinations and runtime-dependent shutdown results exactly as they accumulated behind the facade.
- Because the same live value is shared, code can unwrap once, keep that `AsyncLogger[S]` handle, and then observe `pending_count()`, `state()`, `is_closed()`, or failure fields changing as later facade-level `info(...)`, `log(...)`, `run()`, or `shutdown(...)` calls execute.
- That also means the unwrapped logger can already be both `is_closed=true` and `has_failed=true`, with the same retained `last_error()` string and the same dropped-count cleanup outcome that delegated shutdown left behind.
- That also means the unwrapped logger can already be both `is_closed=true` and `has_failed=true`, with the same retained `last_error()` string and the same runtime-dependent pending-versus-dropped cleanup outcome that delegated shutdown left behind.
- If the wrapped sink type has richer helper APIs, unwrapping also restores access to that same sink helper surface through the original `AsyncLogger[S]` value.
- When the wrapped sink is `RuntimeSink`, that same unwrap also preserves queued runtime state and file-backed helper behavior exactly as they existed behind the facade, including runtime file state snapshots and file control methods.
- Runtime sink helper mutations are still live too. Changing file append mode, auto-flush, rotation, reopen state, or related helper-managed file state through the unwrapped logger changes the same wrapped runtime sink that later facade writes and shutdown behavior continue using.
@@ -87,7 +87,7 @@ e.g.:
- Unwrapping does not convert facade lifecycle history into a simplified snapshot; any retained `last_error()`, pending backlog, dropped counts, or sink runtime details stay exactly as they were on the wrapped logger.
- If facade-level `run()` or `shutdown()` already ended in a failure-retaining state, unwrapping can therefore expose combinations such as `is_closed=true` together with `has_failed=true`, the same `last_error()`, and the same leftover dropped-count cleanup.
- If facade-level `run()` or `shutdown()` already ended in a failure-retaining state, unwrapping can therefore expose combinations such as `is_closed=true` together with `has_failed=true`, the same `last_error()`, and runtime-dependent leftover backlog or dropped-count cleanup.
- Recovering the full async logger also does not translate runtime sink helper state into a simpler snapshot; queue counters, file availability, file failure counters, and runtime file controls stay exactly as they were on the wrapped logger.
@@ -1,15 +0,0 @@
---
name: library-async-logger-with-trace-context
group: api
category: facade
update-time: 20260719
description: Bind TraceContext fields through the restricted LibraryAsyncLogger facade.
key-word:
- library
- async
- trace
---
## Library-async-logger-with-trace-context
`LibraryAsyncLogger::with_trace_context(...)` returns a derived library facade with `trace_id`, `span_id`, `trace_flags`, and optional `trace_state` attached to each later record. It does not start a worker or change lifecycle state.
+4 -4
View File
@@ -2,7 +2,7 @@
name: library-async-logger
group: api
category: facade
update-time: 20260707
update-time: 20260614
description: Public library-facing async logger facade type used to expose a narrower surface than AsyncLogger while preserving sink typing.
key-word:
- library
@@ -34,13 +34,13 @@ Detailed rules explaining key parameters and behaviors
- This is a public facade struct, not a type alias.
- The wrapped sink type `S` is preserved, so sink-specific typing remains available through the facade type parameter.
- The facade keeps common library-safe async operations such as `new(...)`, `with_target(...)`, `child(...)`, `bind(...)`, `is_enabled(...)`, `run()`, `shutdown()`, and the main async write methods `log(...)`, `info(...)`, `warn(...)`, and `error(...)`.
- `LibraryAsyncLogger::new(...)` delegates to `async_logger(...)`, so the same async queue, raising flush callback, and lifecycle behavior still exist behind the narrower facade.
- `LibraryAsyncLogger::new(...)` delegates to `async_logger(...)`, so the same async queue, raising flush callback, and runtime-dependent lifecycle behavior still exist behind the narrower facade.
- Because `new(...)` delegates directly, `AsyncLoggerConfig` values such as pending limits, overflow mode, batch sizing, linger timing, and flush policy are preserved exactly rather than being translated into facade-specific defaults.
- The facade also preserves the wrapped async logger's target rules on its exposed write methods: `log(..., target=...)` can override the target for one call, while `info(...)`, `warn(...)`, and `error(...)` continue using the stored logger target unless the facade first derives another logger with `with_target(...)` or `child(...)`.
- Most facade reshaping helpers keep the same visible sink type, and unlike synchronous `LibraryLogger`, async `with_context_fields(...)` and `bind(...)` also preserve the visible `LibraryAsyncLogger[S]` type because they update stored async context metadata instead of changing the exposed sink wrapper.
- It does not expose the wider `AsyncLogger[S]` composition surface or the async state and lifecycle inspection helpers directly.
- Call `to_async_logger()` when later code must recover the full underlying `AsyncLogger[S]` surface.
- That recovered logger is the same live async value, so queue counters, retained failure state, shutdown outcomes, and sink helper access are preserved rather than recomputed.
- That recovered logger is the same live async value, so queue counters, retained failure state, runtime-dependent shutdown outcomes, and sink helper access are preserved rather than recomputed.
- If the delegated async flush callback fails, the facade preserves the same `has_failed()`, `last_error()`, `is_running()`, pending-backlog, and shutdown-cleanup semantics that the underlying `AsyncLogger[S]` would have exposed directly.
- If `S` is `RuntimeSink`, queued runtime state and file-backed helper behavior also stay on that same wrapped logger value; the facade only hides direct access until `to_async_logger()` is used.
- If `S` is `RuntimeSink` and the value came from `build_library_async_logger(...)` or `parse_and_build_library_async_logger(...)`, the wrapped logger also keeps that sync-first builder route unchanged: any optional `LoggerConfig.queue` was already applied before async wrapping, and `logger.sink.kind` had already decided the concrete `RuntimeSink` variant before the facade narrowed the surface.
@@ -111,7 +111,7 @@ e.g.:
- If the wrapped async logger later ends in a mixed diagnostic state such as `has_failed=true` with retained backlog, unwrapping exposes that exact state instead of a library-specific translation.
- Shutdown through the facade keeps the wrapped logger's failure cleanup behavior: after a worker-side failure, unwrapped retained pending backlog is converted into dropped records before shutdown returns.
- Shutdown through the facade keeps the wrapped logger's runtime-dependent failure cleanup behavior: after a worker-side failure, unwrapped pending versus dropped cleanup can still differ between native-worker and compatibility runtimes.
- Helpers such as `pending_count()`, `dropped_count()`, `is_closed()`, `is_running()`, `has_failed()`, `last_error()`, `flush_policy()`, `state()`, and `wait_idle()` remain on the underlying `AsyncLogger[S]` and require `to_async_logger()` first.
@@ -1,20 +0,0 @@
---
name: library-logger-with-trace-context
group: api
category: facade
update-time: 20260719
description: Bind TraceContext fields through the restricted LibraryLogger facade.
key-word:
- library
- trace
- context
---
## Library-logger-with-trace-context
```moonbit
let logger = LibraryLogger::new(console_sink())
.with_trace_context(trace_context("trace-1", "span-1"))
```
The derived facade preserves its library-facing API while wrapping the sink with context fields. Use `to_logger()` only when broader composition is required.
+4 -4
View File
@@ -13,12 +13,12 @@ key-word:
## Logger-config-to-json
Convert a typed `LoggerConfig` into a `Json`. This helper is the structured export path when config should be persisted, inspected, or embedded into larger JSON payloads.
Convert a typed `LoggerConfig` into a `JsonValue`. This helper is the structured export path when config should be persisted, inspected, or embedded into larger JSON payloads.
### Interface
```moonbit
pub fn logger_config_to_json(config : LoggerConfig) -> Json {}
pub fn logger_config_to_json(config : LoggerConfig) -> @json_parser.JsonValue {}
```
#### input
@@ -27,7 +27,7 @@ pub fn logger_config_to_json(config : LoggerConfig) -> Json {}
#### output
- `Json` - JSON representation of the logger config.
- `JsonValue` - JSON representation of the logger config.
### Explanation
@@ -73,5 +73,5 @@ e.g.:
1. Use this helper when you need a reusable JSON value rather than a final JSON string.
2. Use `stringify_logger_config(...)` when the next consumer expects JSON text instead of `Json`.
2. Use `stringify_logger_config(...)` when the next consumer expects JSON text instead of `JsonValue`.
+5 -6
View File
@@ -2,8 +2,8 @@
name: logger-config-type
group: api
category: config
update-time: 20260707
description: Public logger config type re-exported from config_model for serializable top-level sync settings.
update-time: 20260613
description: Public logger config alias used for serializable top-level sync logger settings.
key-word:
- logger
- config
@@ -13,12 +13,12 @@ key-word:
## Logger-config-type
`LoggerConfig` is the public top-level serializable config type used to describe sync logger behavior. On the root `src` facade, it is re-exported from `src/config_model`, which is the real owner of the concrete logger config model.
`LoggerConfig` is the public top-level serializable config type used to describe sync logger behavior. It is a direct alias to the logger config model used by config parsers, sync logger builders, and async build config embedding.
### Interface
```moonbit
pub using @config_model { type LoggerConfig }
pub type LoggerConfig = @utils.LoggerConfig
```
#### output
@@ -29,8 +29,7 @@ pub using @config_model { type LoggerConfig }
Detailed rules explaining key parameters and behaviors
- This root surface is a re-export, not the concrete owner definition.
- The concrete type lives in `@config_model.LoggerConfig`, not in `@utils`.
- This is a type alias, not a built logger instance.
- The current fields are `min_level : Level`, `target : String`, `timestamp : Bool`, `sink : SinkConfig`, and `queue : QueueConfig?`.
- `LoggerConfig::new(...)` constructs this type as the main sync config entry point.
- `parse_logger_config_text(...)`, `logger_config_to_json(...)`, `stringify_logger_config(...)`, and `build_logger(...)` all consume or produce the same public config shape.
-22
View File
@@ -1,22 +0,0 @@
---
name: logger-with-trace-context
group: api
category: logger
update-time: 20260719
description: Bind a TraceContext to every record from a synchronous Logger.
key-word:
- logger
- trace
- context
---
## Logger-with-trace-context
```moonbit
pub fn[S] Logger::with_trace_context(
self : Logger[S],
context : TraceContext,
) -> Logger[ContextSink[S]]
```
Returns a derived logger that prepends the context fields to every record. The original logger is unchanged. This is equivalent to `with_context_fields(context.as_fields())`, while making trace intent explicit.
-3
View File
@@ -15,8 +15,6 @@ key-word:
Parse a JSON logger definition and build a ready-to-use `ConfiguredLogger`. This is the most direct API when configuration is loaded from files, environment-derived JSON, or external settings systems.
At the public `src` layer, this API is a facade composition of the root parser and root builder: it parses into the shared config model owned by `src/config_model`, then produces a `ConfiguredLogger` backed by `src/runtime.RuntimeSink`.
### Interface
```moonbit
@@ -36,7 +34,6 @@ pub fn parse_and_build_logger(input : String) -> ConfiguredLogger raise ConfigEr
Detailed rules explaining key parameters and behaviors
- Parsing and building are done in one step by calling `parse_logger_config_text(input)` first and then passing the resulting `LoggerConfig` into `build_logger(...)`.
- The resulting file-control and file-diagnostics helpers remain facade methods over `RuntimeSink`, which in turn delegates file behavior to `src/file_runtime` and file model values to `src/file_model`.
- The returned `ConfiguredLogger` is just `Logger[RuntimeSink]`, so it still supports regular logging calls.
- The returned logger also keeps inherited logger target behavior such as `with_target(...)`, `child(...)`, and per-call `target=` overrides on `log(...)`.
- That means `log(..., target=...)` can override the target for one write, while severity helpers such as `info(...)`, `warn(...)`, and `error(...)` continue to use the stored logger target unless a derived logger was created first with `with_target(...)` or `child(...)`.
-3
View File
@@ -15,8 +15,6 @@ key-word:
Parse JSON text into a typed `LoggerConfig`. This API is useful when you want validation and inspection of config data before turning it into a runtime logger.
At the public `src` layer, this parser is a facade over the concrete config parser owned by `src/config_model`, and the returned config object is the shared `@config_model.LoggerConfig` model.
### Interface
```moonbit
@@ -36,7 +34,6 @@ pub fn parse_logger_config_text(input : String) -> LoggerConfig raise ConfigErro
Detailed rules explaining key parameters and behaviors
- Parsing is separated from runtime construction.
- Any parsed file rotation field is stored as the shared `@file_model.FileRotation` model inside `SinkConfig.rotation`.
- This API is ideal for validating, editing, or inspecting config values before calling `build_logger(...)`.
- Supported keys are intentionally constrained to stable built-in sink shapes and formatter options.
- Omitted top-level keys fall back to the same defaults used by the typed config constructors: `min_level=Info`, `target=""`, `timestamp=false`, `sink=default_sink_config()`, and `queue=None`.
+4 -4
View File
@@ -13,12 +13,12 @@ key-word:
## Queue-config-to-json
Convert a typed `QueueConfig` into a `Json`. This helper is the structured export path for synchronous queue wrapper configuration when callers want machine-readable config output.
Convert a typed `QueueConfig` into a `JsonValue`. This helper is the structured export path for synchronous queue wrapper configuration when callers want machine-readable config output.
### Interface
```moonbit
pub fn queue_config_to_json(queue : QueueConfig) -> Json {}
pub fn queue_config_to_json(queue : QueueConfig) -> @json_parser.JsonValue {}
```
#### input
@@ -27,7 +27,7 @@ pub fn queue_config_to_json(queue : QueueConfig) -> Json {}
#### output
- `Json` - Structured JSON representation of the queue config.
- `JsonValue` - Structured JSON representation of the queue config.
### Explanation
@@ -74,5 +74,5 @@ e.g.:
1. Use this helper when you need a reusable JSON value rather than a final JSON string.
2. Use `stringify_queue_config(...)` when the next consumer expects text instead of `Json`.
2. Use `stringify_queue_config(...)` when the next consumer expects text instead of `JsonValue`.
+5 -6
View File
@@ -2,8 +2,8 @@
name: queue-config-type
group: api
category: config
update-time: 20260707
description: Public queue config type re-exported from config_model for serializable sync queue settings.
update-time: 20260613
description: Public queue config alias used for serializable synchronous queue wrapping settings.
key-word:
- queue
- config
@@ -13,12 +13,12 @@ key-word:
## Queue-config-type
`QueueConfig` is the public serializable config type used to describe synchronous queue wrapping. On the root `src` facade, it is re-exported from `src/config_model`, which is the real owner of the concrete queue config model.
`QueueConfig` is the public serializable config type used to describe synchronous queue wrapping. It is a direct alias to the queue config model used by sync logger configuration, parsers, and queue config serializers.
### Interface
```moonbit
pub using @config_model { type QueueConfig }
pub type QueueConfig = @utils.QueueConfig
```
#### output
@@ -29,8 +29,7 @@ pub using @config_model { type QueueConfig }
Detailed rules explaining key parameters and behaviors
- This root surface is a re-export, not the concrete owner definition.
- The concrete type lives in `@config_model.QueueConfig`, not in `@utils`.
- This is a type alias, not a runtime queue instance.
- The current fields are `max_pending : Int` and `overflow : QueueOverflowPolicy`.
- `QueueConfig::new(...)` constructs this type as the normal handwritten entry point.
- `queue_config_to_json(...)` and `stringify_queue_config(...)` serialize the same public config shape for tooling or persistence.
+2 -3
View File
@@ -13,12 +13,12 @@ key-word:
## Queue-overflow-policy
`QueueOverflowPolicy` is the public enum that defines what a synchronous queue should do when it reaches `max_pending`. It is a direct alias to the shared queue model enum used by both `QueuedSink` and `QueueConfig`.
`QueueOverflowPolicy` is the public enum that defines what a synchronous queue should do when it reaches `max_pending`. It is a direct alias to the queue model enum used by both `QueuedSink` and `QueueConfig`.
### Interface
```moonbit
pub type QueueOverflowPolicy = @queue_model.QueueOverflowPolicy
pub type QueueOverflowPolicy = @utils.QueueOverflowPolicy
```
#### output
@@ -32,7 +32,6 @@ Detailed rules explaining key parameters and behaviors
- This is a type alias, not a separate policy wrapper.
- `QueueOverflowPolicy::DropNewest` keeps the existing queued records and drops the incoming one when the queue is full.
- `QueueOverflowPolicy::DropOldest` removes one pending record and enqueues the new record instead.
- The concrete owner is the shared `@queue_model` package, so config-side and sink-side queue APIs reference the same model without making config packages depend on sink runtime packages.
- The same enum is used by code-side queue composition through `queued_sink(...)` and config-driven queue composition through `QueueConfig::new(...)`.
### How to Use
-1
View File
@@ -37,7 +37,6 @@ Detailed rules explaining key parameters and behaviors
- This is a public root struct, not a type alias.
- The current fields are `sink : S`, `queue : @queue.Queue[Record]`, `max_pending : Int`, `overflow : QueueOverflowPolicy`, and `dropped_count : Ref[Int]`.
- The `overflow` field resolves to the shared `@queue_model.QueueOverflowPolicy` owner.
- `queued_sink(...)` constructs this type directly from a wrapped sink and queue policy.
- The sink preserves the wrapped sink type `S`, which is useful when typed composition still matters after queueing is introduced.
+3 -7
View File
@@ -13,12 +13,12 @@ key-word:
## Runtime-file-state-to-json
Convert `RuntimeFileState` into a `Json`. On the root `src` facade, this helper forwards to the concrete serializer owned by `src/file_model`.
Convert `RuntimeFileState` into a `JsonValue`. This helper exports both file sink status and queue metrics for combined runtime file diagnostics.
### Interface
```moonbit
pub fn runtime_file_state_to_json(state : RuntimeFileState) -> Json {}
pub fn runtime_file_state_to_json(state : RuntimeFileState) -> @json_parser.JsonValue {}
```
#### input
@@ -27,18 +27,16 @@ pub fn runtime_file_state_to_json(state : RuntimeFileState) -> Json {}
#### output
- `Json` - Structured JSON representation of the runtime file state.
- `JsonValue` - Structured JSON representation of the runtime file state.
### Explanation
Detailed rules explaining key parameters and behaviors
- The output includes `file`, `queued`, `pending_count`, and `dropped_count`.
- The root surface forwards to `@file_model.runtime_file_state_to_json(...)`, which is the real owner of this serialization logic.
- `file` is itself exported as a nested file sink state object.
- This helper is richer than `file_sink_state_to_json(...)` because it also carries queue wrapping context.
- It is useful for `RuntimeSink::file_runtime_state()`, `ConfiguredLogger::file_runtime_state()`, and similar queued-file diagnostics flows.
- Any `file_rotation_i64(...)` policy nested under `file` includes both the compatibility `max_bytes` number and `max_bytes_i64` as a string.
### How to Use
@@ -80,5 +78,3 @@ e.g.:
1. Use this helper when file and queue runtime context should stay together.
2. It is especially useful for queued file runtime paths, whether accessed directly or through configured loggers.
3. For wide native rotation policies nested under `file.rotation`, use `max_bytes_i64` when exact threshold recovery matters.
+5 -6
View File
@@ -2,8 +2,8 @@
name: runtime-file-state
group: api
category: runtime
update-time: 20260707
description: Public combined file-and-queue runtime state re-exported from file_model for runtime diagnostics.
update-time: 20260613
description: Public combined file-and-queue runtime state alias used by runtime file diagnostics.
key-word:
- runtime
- file
@@ -13,12 +13,12 @@ key-word:
## Runtime-file-state
`RuntimeFileState` is the public snapshot object that combines file state with queue runtime context for file-backed runtime diagnostics. On the root `src` facade, it is re-exported from `src/file_model`, which is the real owner of the concrete runtime file state model.
`RuntimeFileState` is the public snapshot object that combines file state with queue runtime context for file-backed runtime diagnostics. It is a direct alias to the runtime model used by `RuntimeSink`, `ConfiguredLogger`, and JSON export helpers.
### Interface
```moonbit
pub using @file_model { type RuntimeFileState }
pub type RuntimeFileState = @utils.RuntimeFileState
```
#### output
@@ -29,8 +29,7 @@ pub using @file_model { type RuntimeFileState }
Detailed rules explaining key parameters and behaviors
- This root surface is a re-export, not the concrete owner definition.
- The concrete type lives in `@file_model.RuntimeFileState`, not in `@utils`.
- This is a type alias, not a live runtime controller.
- The current fields are `file : FileSinkState`, `queued : Bool`, `pending_count : Int`, and `dropped_count : Int`.
- This type is returned by `RuntimeSink::file_runtime_state()` and by `ConfiguredLogger::file_runtime_state()` when file runtime context is available.
- It is broader than `FileSinkState` because it also reports whether queue wrapping is involved and how the queue is behaving.
+7 -13
View File
@@ -2,8 +2,8 @@
name: runtime-sink-close
group: api
category: runtime
update-time: 20260707
description: Close a RuntimeSink and report whether the concrete close path succeeded.
update-time: 20260613
description: Close a RuntimeSink and report whether the underlying sink performed a successful close action.
key-word:
- runtime
- sink
@@ -27,7 +27,7 @@ pub fn RuntimeSink::close(self : RuntimeSink) -> Bool {
#### output
- `Bool` - Whether the concrete runtime sink reported a successful close path.
- `Bool` - Whether the concrete runtime sink reported a successful close action.
### Explanation
@@ -35,11 +35,9 @@ Detailed rules explaining key parameters and behaviors
- Plain console-style runtime sinks return `true` because they do not have a meaningful close step here.
- Plain file runtime sinks forward directly to `FileSink::close()`.
- Queued file runtime sinks now follow the same safe teardown path as `file_close()`: they first try to drain the queue, then flush the wrapped file sink, then close it.
- On `QueuedFile`, the returned `Bool` is `true` only when that whole teardown path succeeds without introducing new file failures.
- Queue-wrapped console-style runtime sinks also use drain-first teardown.
- For `QueuedConsole`, `QueuedJsonConsole`, and `QueuedTextConsole`, `close()` consumes pending queue items before reporting success.
- Because these wrapped console-style sinks do not expose an additional close-failure channel, success for these variants means the backlog was drained to zero.
- Queued file runtime sinks close the wrapped file sink rather than only the queue wrapper.
- Generic `close()` on `QueuedFile` does not drain or flush queued records first; it closes the inner file sink directly.
- Queue-wrapped console-style runtime sinks return `true` as a no-op success.
- This method is the direct sink-level API used by `ConfiguredLogger::close(...)`.
- For file-backed runtime sinks, later `close()` calls return `false` after the handle has already been cleared.
@@ -74,14 +72,10 @@ e.g.:
- If callers know they are working with a direct `FileSink`, `FileSink::close()` is the narrower API.
- On queued file sinks, `true` still does not mean the records are guaranteed to be durable beyond what the current backend can report; it means the queue-drain, file-flush, and file-close path completed without a newly observed file failure.
- On queued non-file sinks, `true` means the queued backlog was consumed before teardown completed.
### Notes
1. Use this helper when code is managing a `RuntimeSink` value directly.
2. Generic `close()` is now safe for queue-backed runtime sinks and no longer skips queued records silently.
2. Use `file_close()` instead of generic `close()` when queued file sinks should flush pending records before file teardown.
3. `ConfiguredLogger::close(...)` is the higher-level wrapper for config-built loggers.
-80
View File
@@ -1,80 +0,0 @@
---
name: runtime-sink-drain-progress
group: api
category: runtime
update-time: 20260707
description: Return a structured generic drain progress snapshot for a RuntimeSink without collapsing queue and plain-file fallback semantics into one Int.
key-word:
- runtime
- sink
- drain
- public
---
## Runtime-sink-drain-progress
Return a structured generic drain progress snapshot for a `RuntimeSink`. This is the recommended truthful generic runtime drain helper when callers need bounded or full queue progress without relying on the compatibility `Int` returned by `drain()`.
### Interface
```moonbit
pub fn RuntimeSink::drain_progress(
self : RuntimeSink,
max_items~ : Int = -1,
) -> RuntimeSinkProgress {
```
#### input
- `self : RuntimeSink` - Runtime sink whose generic drain progress should be observed.
- `max_items : Int` - Optional upper bound on drained queued items. Negative values mean no explicit bound.
#### output
- `RuntimeSinkProgress` - Structured progress snapshot separating queue advancement from plain-file flush fallback steps.
### Explanation
Detailed rules explaining key parameters and behaviors
- Queue-wrapped runtime sinks report consumed queued items through `queue_advanced_count` and honor `max_items`.
- Plain file runtime sinks still follow the generic fallback path and report `FileSink::flush()` as `file_flush_step_count` `1` or `0`.
- Plain console-style runtime sinks return a zeroed snapshot because they do not own a drainable queue here.
- Queued file runtime sinks report queue advancement, while delayed file delivery failures still belong to file failure counters and `file_flush()`.
- This helper preserves the old runtime behavior but makes the meaning explicit in the result shape.
- `drain()` remains available as the legacy convenience wrapper that sums the fields back into one count.
### How to Use
Here are some specific examples provided.
#### When Need Recommended Bounded Generic Drain Progress
When code should observe one bounded drain step without mixing units:
```moonbit
let progress = sink.drain_progress(max_items=16)
```
In this example, queue progress and plain-file fallback stay separated.
#### When Need A Full Manual Generic Drain Snapshot
When support code should empty queued work and keep runtime-shape context:
```moonbit
let progress = sink.drain_progress()
```
In this example, the caller can inspect both the count and the runtime shape afterwards.
### Error Case
e.g.:
- If the runtime sink is not queue-backed, the snapshot may stay zeroed or use the plain-file fallback field.
- If callers want file-specific success semantics after queue delivery, `file_flush()` is the better API.
### Notes
1. Prefer `drain_progress()` over `drain()` in new generic runtime code.
2. Use `pending_count()` together with this helper when remaining backlog must also be observed.
+15 -23
View File
@@ -2,8 +2,8 @@
name: runtime-sink-drain
group: api
category: runtime
update-time: 20260707
description: Compatibility RuntimeSink drain helper that still returns one Int by collapsing generic queue progress and plain-file fallback steps.
update-time: 20260613
description: Drain queued work from a RuntimeSink with an optional item limit.
key-word:
- runtime
- sink
@@ -13,7 +13,7 @@ key-word:
## Runtime-sink-drain
Drain queued work from a `RuntimeSink` and return one compatibility count. This helper is still available for older code, but new generic runtime code should prefer `drain_progress()` because it exposes queue advancement and plain-file fallback steps separately.
Drain queued work from a `RuntimeSink`. This helper is useful when code owns a runtime sink directly and needs controlled queue progress.
### Interface
@@ -28,18 +28,16 @@ pub fn RuntimeSink::drain(self : RuntimeSink, max_items~ : Int = -1) -> Int {
#### output
- `Int` - Compatibility count produced from the structured `drain_progress()` result.
- `Int` - Number of drained items, or the fallback flush count for plain file sinks.
### Explanation
Detailed rules explaining key parameters and behaviors
- This method now delegates to `drain_progress()` and sums `queue_advanced_count + file_flush_step_count` back into one compatibility number.
- Queue-wrapped runtime sinks still report how many queued records were consumed during the drain.
- A queued file drain can still return a positive number even when file failure counters increase during the same queue-delivery step.
- Plain file runtime sinks still use the generic `FileSink::flush()` fallback and therefore still return `1` or `0`.
- Plain console-style runtime sinks still return `0` because the structured result stays zeroed.
- This method remains the direct sink-level API used by `ConfiguredLogger::drain(...)`.
- Queue-wrapped runtime sinks forward to the wrapped queue sink's `drain(...)` behavior.
- Plain file runtime sinks fall back to `FileSink::flush()` behavior and return `1` or `0`.
- Plain console-style runtime sinks return `0` because they do not own a drainable queue.
- This method is the direct sink-level API used by `ConfiguredLogger::drain(...)`.
### How to Use
@@ -47,37 +45,31 @@ Here are some specific examples provided.
#### When Need Bounded Queue Progress
When older code already expects one numeric drain count:
When direct queue-backed runtime work should be advanced in chunks:
```moonbit
let drained = sink.drain(max_items=16)
```
In this example, callers still cap how much queued work is processed in one step while keeping the legacy return shape.
In this example, callers cap how much queued work is processed in one step.
#### When Need Full Manual Drain
When code should keep the older full-drain compatibility path:
When a runtime queue should be emptied without an explicit item cap:
```moonbit
ignore(sink.drain())
```
In this example, the runtime sink drains as much queued work as its concrete variant allows while still returning one numeric count.
In this example, the runtime sink drains as much queued work as its concrete variant allows.
### Error Case
e.g.:
- If the runtime sink is not queue-backed, the result may be `0` or file-flush fallback behavior.
- If callers need truthful generic progress semantics, `drain_progress()` is the better API.
- If callers only need generic flush semantics, `flush_progress()` may be the simpler structured API.
- If callers need file-specific success semantics after draining a queued file sink, they should inspect failure counters or use `file_flush()` for the file-specific path.
- If callers only need generic flush semantics, `flush()` may be the simpler API.
### Notes
1. Treat this method as a compatibility helper for older numeric code.
1. Prefer this helper when queue progress should be bounded or directly observed.
2. Prefer `drain_progress()` in new generic runtime code.
3. `ConfiguredLogger::drain(...)` is the higher-level wrapper for config-built loggers.
2. `ConfiguredLogger::drain(...)` is the higher-level wrapper for config-built loggers.
+3 -7
View File
@@ -2,7 +2,7 @@
name: runtime-sink-file-available
group: api
category: runtime
update-time: 20260707
update-time: 20260613
description: Read whether a RuntimeSink currently has an available file sink behind its runtime sink shape.
key-word:
- runtime
@@ -36,8 +36,6 @@ Detailed rules explaining key parameters and behaviors
- Plain `File` runtime variants report actual file availability.
- `QueuedFile` runtime variants expose the availability of their wrapped inner file sink.
- Non-file runtime variants return `false`.
- This means `false` currently merges two different situations: “not file-backed” and “file-backed but currently unavailable”.
- Use `file_path_or_none()`, `file_policy_or_none()`, `file_default_policy_or_none()`, `file_state_or_none()`, or `file_runtime_state()` when callers need truthful file-semantics detection.
- This helper does not mutate runtime sink state.
### How to Use
@@ -69,12 +67,10 @@ In this example, callers can decide whether a recovery action is needed.
e.g.:
- If the runtime sink is not file-backed, the method returns `false`.
- If callers need to distinguish “not file-backed from “file-backed but unavailable”, use one of the truthful `*_or_none()` helpers or `file_runtime_state()`.
- If callers need detailed failure counters rather than a simple availability flag, `file_state_or_none()` or `file_runtime_state()` is the better API.
- If callers need detailed failure counters rather than a simple availability flag, `file_state()` or `file_runtime_state()` is the better API.
### Notes
1. Use this helper for lightweight file sink health checks on direct `RuntimeSink` values.
2. Pair it with reopen and failure-counter APIs when diagnosing file sink problems, but prefer the truthful `*_or_none()` helpers when file semantics themselves must be checked.
2. Pair it with reopen and failure-counter APIs when diagnosing file sink problems.
+38 -9
View File
@@ -2,8 +2,8 @@
name: runtime-sink-file-clear-rotation
group: api
category: runtime
update-time: 20260707
description: Clear the rotation policy used by a file-backed RuntimeSink.
update-time: 20260613
description: Disable runtime rotation on a file-backed RuntimeSink.
key-word:
- runtime
- sink
@@ -13,7 +13,7 @@ key-word:
## Runtime-sink-file-clear-rotation
Clear the rotation policy used by a file-backed `RuntimeSink`.
Disable runtime rotation on a file-backed `RuntimeSink`. This helper is the direct shortcut for clearing rotation policy from a runtime sink value.
### Interface
@@ -23,7 +23,7 @@ pub fn RuntimeSink::file_clear_rotation(self : RuntimeSink) -> Bool {
#### input
- `self : RuntimeSink` - Runtime sink whose file rotation policy should be cleared.
- `self : RuntimeSink` - Runtime sink whose rotation policy should be cleared.
#### output
@@ -33,13 +33,42 @@ pub fn RuntimeSink::file_clear_rotation(self : RuntimeSink) -> Bool {
Detailed rules explaining key parameters and behaviors
- Plain `File` runtime variants clear the wrapped `FileSink` rotation policy and return `true`.
- `QueuedFile` runtime variants clear the wrapped inner `FileSink` rotation policy only when no queued records are pending.
- Plain `File` runtime variants clear rotation on the wrapped `FileSink` and return `true`.
- `QueuedFile` runtime variants forward the update to the wrapped inner `FileSink` and return `true`.
- Non-file runtime variants return `false`.
- If a queued file sink still has pending records, the update is rejected and returns `false` so already queued records are not later written under a different rotation policy than the one they were queued under.
- This helper is equivalent in intent to setting rotation to `None`, but is clearer at the call site.
### How to Use
Here are some specific examples provided.
#### When Need To Disable Rotation Explicitly
When runtime file rotation should be turned off on a direct sink value:
```moonbit
ignore(sink.file_clear_rotation())
```
In this example, rotation policy is removed directly.
#### When Need A Clear Intent Shortcut
When code should make the disable-rotation intent obvious:
```moonbit
let ok = sink.file_clear_rotation()
```
In this example, the call site reads more clearly than a generic config setter.
### Error Case
e.g.:
- If the runtime sink is not file-backed, the method returns `false`.
- If callers need to switch to another rotation config rather than disable rotation, `file_set_rotation(...)` is the better API.
### Notes
1. Use this helper when runtime rotation policy should be removed without rebuilding the sink.
1. Use this helper when the desired effect is simply `rotation off`.
2. On queued file sinks, clear pending records first so policy mutation does not retroactively affect already queued writes.
2. It is clearer than passing `None` through a broader setter when intent matters.
+7 -9
View File
@@ -2,8 +2,8 @@
name: runtime-sink-file-close
group: api
category: runtime
update-time: 20260707
description: Close the file sink behind a RuntimeSink when one is present, with queued-file success tied to safe drain-flush-close behavior.
update-time: 20260613
description: Close the file sink behind a RuntimeSink when one is present.
key-word:
- runtime
- sink
@@ -27,15 +27,15 @@ pub fn RuntimeSink::file_close(self : RuntimeSink) -> Bool {
#### output
- `Bool` - Whether the file-specific close path succeeded.
- `Bool` - Whether the underlying file close succeeded.
### Explanation
Detailed rules explaining key parameters and behaviors
- Plain `File` runtime variants forward directly to `FileSink::close()`.
- `QueuedFile` runtime variants first drain the queue, then flush the wrapped file sink, then close it.
- For `QueuedFile`, the returned `Bool` is `true` only when that whole path succeeds and no new write, flush, or rotation failures are observed during the drain-flush-close step.
- `QueuedFile` runtime variants first attempt `sink.flush()` on the queue wrapper, then call `sink.sink.close()` on the wrapped file sink.
- For `QueuedFile`, the queue flush result is ignored and the returned `Bool` comes from the inner file close.
- Non-file runtime variants return `false`.
- After a file-backed runtime sink has already cleared its handle, later `file_close()` calls return `false`.
@@ -59,7 +59,7 @@ When application code wants the direct file close outcome:
let closed = sink.file_close()
```
In this example, the result describes the file-specific close path rather than generic sink close behavior.
In this example, the result describes file close behavior rather than generic sink close behavior.
### Error Case
@@ -70,10 +70,8 @@ e.g.:
- If callers only need generic sink teardown, `close()` is the broader API.
- On queued file sinks, `true` still does not mean a stronger durability contract than the current backend can report; it means the safe drain-flush-close path completed without a newly observed file failure.
### Notes
1. Prefer this helper when direct runtime code specifically cares about file-backed shutdown.
2. Generic `close()` now uses the same safe queued-file teardown path.
2. Queued file sinks flush pending records before closing the file, unlike generic `close()`.
@@ -1,82 +0,0 @@
---
name: runtime-sink-file-default-policy-or-none
group: api
category: runtime
update-time: 20260707
description: Read the default runtime file policy from a RuntimeSink only when it is actually file-backed.
key-word:
- runtime
- sink
- file
- truthful
---
## Runtime-sink-file-default-policy-or-none
Read the default runtime file policy from a `RuntimeSink` only when it is actually file-backed.
The returned `FileSinkPolicy` value is owned by `src/file_model`; this method belongs to the runtime facade layer and avoids fabricating that model on non-file variants.
This is the truthful companion to `file_default_policy()`. Prefer it when default-policy inspection should not fabricate a fallback object on non-file sinks.
### Interface
```moonbit
pub fn RuntimeSink::file_default_policy_or_none(self : RuntimeSink) -> FileSinkPolicy? {
```
#### input
- `self : RuntimeSink` - Runtime sink whose default file policy should be inspected.
#### output
- `FileSinkPolicy?` - `Some(policy)` when the runtime sink is file-backed, otherwise `None`.
### Explanation
Detailed rules explaining key parameters and behaviors
- Plain `File` runtime variants return `Some(default_policy)`.
- `QueuedFile` runtime variants forward the wrapped inner file sink default policy as `Some(default_policy)`.
- The wrapped value is the shared `@file_model.FileSinkPolicy` model, not a runtime-owned concrete type.
- Non-file runtime variants return `None`.
- This helper is useful when callers need to compare runtime drift or restore defaults without fabricating file semantics.
### How to Use
Here are some specific examples provided.
#### When Need Truthful Baseline Policy Visibility
When tooling should inspect defaults only for real file-backed sinks:
```moonbit
let defaults = sink.file_default_policy_or_none()
```
In this example, `None` means the runtime sink has no file default policy.
#### When Compare Current And Default Policy Truthfully
When diagnostics should avoid fallback policy objects:
```moonbit
match (sink.file_policy_or_none(), sink.file_default_policy_or_none()) {
(Some(current), Some(defaults)) => ignore((current, defaults))
_ => ()
}
```
In this example, comparisons happen only when real file semantics exist.
### Error Case
e.g.:
- If the runtime sink is not file-backed, the method returns `None`.
- If callers only need a drift boolean, `file_policy_matches_default()` remains simpler.
### Notes
1. Prefer this helper over `file_default_policy()` for truthful runtime diagnostics.
2. `file_default_policy()` remains available as the compatibility fallback API.
@@ -15,8 +15,6 @@ key-word:
Read the initial default file policy associated with a `RuntimeSink`. This helper exposes the baseline file policy captured when the runtime sink was created.
The returned `FileSinkPolicy` value is owned by `src/file_model`; this method belongs to the runtime facade layer and reads defaults through `src/runtime` over file-backed variants that ultimately use `src/file_runtime.FileSink`.
### Interface
```moonbit
@@ -37,7 +35,6 @@ Detailed rules explaining key parameters and behaviors
- Plain `File` runtime variants return the default policy captured at creation time.
- `QueuedFile` runtime variants forward the default policy from the wrapped inner `FileSink`.
- The returned policy object itself is the shared `@file_model.FileSinkPolicy` model, not a runtime-owned concrete type.
- Non-file runtime variants return the neutral fallback policy `FileSinkPolicy::new(append=false, auto_flush=false, rotation=None)`.
- This helper is useful when callers need to compare runtime drift or restore defaults later.
+8 -10
View File
@@ -2,8 +2,8 @@
name: runtime-sink-file-flush
group: api
category: runtime
update-time: 20260707
description: Flush the file sink behind a RuntimeSink when one is present, with queued-file success tied to both queue drain and file flush outcome.
update-time: 20260614
description: Flush the file sink behind a RuntimeSink when one is present.
key-word:
- runtime
- sink
@@ -27,16 +27,16 @@ pub fn RuntimeSink::file_flush(self : RuntimeSink) -> Bool {
#### output
- `Bool` - Whether the file-specific flush path succeeded.
- `Bool` - Whether the underlying file flush succeeded.
### Explanation
Detailed rules explaining key parameters and behaviors
- Plain `File` runtime variants forward directly to `FileSink::flush()`.
- `QueuedFile` runtime variants first drain the queue, then flush the wrapped file sink.
- For `QueuedFile`, the returned `Bool` is `true` only when all queued records were consumed, the final file flush succeeded, and no new write, flush, or rotation failures were observed during that flush path.
- For `QueuedFile`, this step may also be the point where queued records finally reach the inner file sink, so failure counters can change here even if earlier `log(...)` calls only enqueued records.
- `QueuedFile` runtime variants first attempt `sink.flush()` on the queue wrapper, then call `sink.sink.flush()` on the wrapped file sink.
- For `QueuedFile`, the queue flush result is ignored and the returned `Bool` comes from the inner file flush.
- For `QueuedFile`, this step may also be the point where queued records finally reach the inner file sink, so write-failure counters can change here even if earlier `log(...)` calls only enqueued records.
- Non-file runtime variants return `false`.
- After a file-backed runtime sink has already cleared its handle, later `file_flush()` calls return `false`.
@@ -60,7 +60,7 @@ When code should branch on the outcome of a direct file flush:
let ok = sink.file_flush()
```
In this example, callers can distinguish file-specific flush success from a non-file sink shape.
In this example, callers can distinguish file flush success from a non-file sink shape.
### Error Case
@@ -71,12 +71,10 @@ e.g.:
- If callers want generic queue or sink advancement instead of file-specific behavior, `flush()` is the broader API.
- On queued file sinks, a `false` result may mean queue consumption happened but file delivery still observed a new failure.
### Notes
1. Prefer this helper when direct runtime code specifically cares about file flush behavior.
2. Queued file sinks may perform both queue drain work and file flush work here, including surfacing delayed failures from previously queued records.
2. Queued file sinks may perform both queue flush work and file flush work here, including surfacing delayed write failures from previously queued records.
3. Library or application facades that share the same wrapped file-backed runtime sink still observe the same flush availability state.

Some files were not shown because too many files have changed in this diff Show More