[{"data":1,"prerenderedAt":1352},["ShallowReactive",2],{"navigation_docs_en":3,"-en-logx-monolog":448,"-en-logx-monolog-surround":1347},[4,45,120,157,173,203,233,259,271,287,307,326,339,356,373,386,398,425],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":44},"Getting Started","i-lucide-rocket","\u002Fen\u002Fgetting-started","en\u002F01.getting-started",[10,15,20,25,30,35,40],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fen\u002Fgetting-started\u002Fintroduction","en\u002F01.getting-started\u002F1.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Installation","\u002Fen\u002Fgetting-started\u002Finstallation","en\u002F01.getting-started\u002F2.installation","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":24},"Your first module","\u002Fen\u002Fgetting-started\u002Ffirst-module","en\u002F01.getting-started\u002F3.first-module","i-lucide-package-plus",{"title":26,"path":27,"stem":28,"icon":29},"Project structure","\u002Fen\u002Fgetting-started\u002Fproject-structure","en\u002F01.getting-started\u002F4.project-structure","i-lucide-folder-tree",{"title":31,"path":32,"stem":33,"icon":34},"The shop sample application","\u002Fen\u002Fgetting-started\u002Fsample-app","en\u002F01.getting-started\u002F5.sample-app","i-lucide-shopping-cart",{"title":36,"path":37,"stem":38,"icon":39},"Coming from Laravel","\u002Fen\u002Fgetting-started\u002Fcoming-from-laravel","en\u002F01.getting-started\u002F6.coming-from-laravel","i-lucide-arrow-right-left",{"title":41,"path":42,"stem":43,"icon":39},"Coming from Symfony","\u002Fen\u002Fgetting-started\u002Fcoming-from-symfony","en\u002F01.getting-started\u002F7.coming-from-symfony",false,{"title":46,"icon":47,"path":48,"stem":49,"children":50,"page":44},"CLI Reference","i-lucide-terminal","\u002Fen\u002Fcli","en\u002F02.cli",[51,55,60,65,70,75,80,85,90,95,100,105,110,115],{"title":52,"path":53,"stem":54,"icon":47},"Overview","\u002Fen\u002Fcli\u002Foverview","en\u002F02.cli\u002F1.overview",{"title":56,"path":57,"stem":58,"icon":59},"add compose \u002F add docker","\u002Fen\u002Fcli\u002Fadd-compose","en\u002F02.cli\u002F10.add-compose","i-lucide-container",{"title":61,"path":62,"stem":63,"icon":64},"add mail","\u002Fen\u002Fcli\u002Fadd-mail","en\u002F02.cli\u002F11.add-mail","i-lucide-mail-plus",{"title":66,"path":67,"stem":68,"icon":69},"add notification","\u002Fen\u002Fcli\u002Fadd-notification","en\u002F02.cli\u002F12.add-notification","i-lucide-bell-plus",{"title":71,"path":72,"stem":73,"icon":74},"add realtime","\u002Fen\u002Fcli\u002Fadd-realtime","en\u002F02.cli\u002F13.add-realtime","i-lucide-radio-tower",{"title":76,"path":77,"stem":78,"icon":79},"add seeder","\u002Fen\u002Fcli\u002Fadd-seeder","en\u002F02.cli\u002F14.add-seeder","i-lucide-sprout",{"title":81,"path":82,"stem":83,"icon":84},"new project","\u002Fen\u002Fcli\u002Fnew-project","en\u002F02.cli\u002F2.new-project","i-lucide-folder-plus",{"title":86,"path":87,"stem":88,"icon":89},"new module","\u002Fen\u002Fcli\u002Fnew-module","en\u002F02.cli\u002F3.new-module","i-lucide-blocks",{"title":91,"path":92,"stem":93,"icon":94},"add surface","\u002Fen\u002Fcli\u002Fadd-surface","en\u002F02.cli\u002F4.add-surface","i-lucide-layers-2",{"title":96,"path":97,"stem":98,"icon":99},"add domain","\u002Fen\u002Fcli\u002Fadd-domain","en\u002F02.cli\u002F5.add-domain","i-lucide-box",{"title":101,"path":102,"stem":103,"icon":104},"add handler","\u002Fen\u002Fcli\u002Fadd-handler","en\u002F02.cli\u002F6.add-handler","i-lucide-webhook",{"title":106,"path":107,"stem":108,"icon":109},"new migration","\u002Fen\u002Fcli\u002Fnew-migration","en\u002F02.cli\u002F7.new-migration","i-lucide-file-plus",{"title":111,"path":112,"stem":113,"icon":114},"worker generators","\u002Fen\u002Fcli\u002Fworker-generators","en\u002F02.cli\u002F8.worker-generators","i-lucide-cog",{"title":116,"path":117,"stem":118,"icon":119},"add db","\u002Fen\u002Fcli\u002Fadd-db","en\u002F02.cli\u002F9.add-db","i-lucide-database-zap",{"title":121,"icon":99,"path":122,"stem":123,"children":124,"page":44},"Framework","\u002Fen\u002Fframework","en\u002F03.framework",[125,128,133,138,142,147,152],{"title":52,"path":126,"stem":127,"icon":99},"\u002Fen\u002Fframework\u002Foverview","en\u002F03.framework\u002F1.overview",{"title":129,"path":130,"stem":131,"icon":132},"Application lifecycle","\u002Fen\u002Fframework\u002Fapp","en\u002F03.framework\u002F2.app","i-lucide-power",{"title":134,"path":135,"stem":136,"icon":137},"Server","\u002Fen\u002Fframework\u002Fserver","en\u002F03.framework\u002F3.server","i-lucide-server",{"title":139,"path":140,"stem":141,"icon":114},"Worker","\u002Fen\u002Fframework\u002Fworker","en\u002F03.framework\u002F4.worker",{"title":143,"path":144,"stem":145,"icon":146},"Realtime","\u002Fen\u002Fframework\u002Frealtime","en\u002F03.framework\u002F5.realtime","i-lucide-radio",{"title":148,"path":149,"stem":150,"icon":151},"Migrations","\u002Fen\u002Fframework\u002Fmigrations","en\u002F03.framework\u002F6.migrations","i-lucide-file-stack",{"title":153,"path":154,"stem":155,"icon":156},"Social login","\u002Fen\u002Fframework\u002Fsocial-login","en\u002F03.framework\u002F7.social-login","i-lucide-log-in",{"title":158,"icon":159,"path":160,"stem":161,"children":162,"page":44},"Reference","i-lucide-book-open","\u002Fen\u002Freference","en\u002F04.reference",[163,168],{"title":164,"path":165,"stem":166,"icon":167},"Configuration","\u002Fen\u002Freference\u002Fconfiguration","en\u002F04.reference\u002F1.configuration","i-lucide-settings",{"title":169,"path":170,"stem":171,"icon":172},"External dependencies","\u002Fen\u002Freference\u002Fdependencies","en\u002F04.reference\u002F2.dependencies","i-lucide-package",{"title":174,"icon":175,"path":176,"stem":177,"children":178,"page":44},"Concepts","i-lucide-lightbulb","\u002Fen\u002Fconcepts","en\u002F05.concepts",[179,184,189,193,198],{"title":180,"path":181,"stem":182,"icon":183},"Architecture","\u002Fen\u002Fconcepts\u002Farchitecture","en\u002F05.concepts\u002F1.architecture","i-lucide-layers",{"title":185,"path":186,"stem":187,"icon":188},"Error model","\u002Fen\u002Fconcepts\u002Ferror-model","en\u002F05.concepts\u002F2.error-model","i-lucide-shield-alert",{"title":164,"path":190,"stem":191,"icon":192},"\u002Fen\u002Fconcepts\u002Fconfiguration","en\u002F05.concepts\u002F3.configuration","i-lucide-settings-2",{"title":194,"path":195,"stem":196,"icon":197},"Codegen pipeline","\u002Fen\u002Fconcepts\u002Fcodegen-pipeline","en\u002F05.concepts\u002F4.codegen-pipeline","i-lucide-file-json",{"title":199,"path":200,"stem":201,"icon":202},"Design patterns","\u002Fen\u002Fconcepts\u002Fdesign-patterns","en\u002F05.concepts\u002F5.design-patterns","i-lucide-puzzle",{"title":204,"icon":205,"path":206,"stem":207,"children":208,"page":44},"auth","i-lucide-shield-check","\u002Fen\u002Fauth","en\u002F06.auth",[209,214,219,224,229],{"title":210,"path":211,"stem":212,"icon":213},"Authentication","\u002Fen\u002Fauth\u002Foverview","en\u002F06.auth\u002F1.overview","i-lucide-key-round",{"title":215,"path":216,"stem":217,"icon":218},"RBAC","\u002Fen\u002Fauth\u002Frbac","en\u002F06.auth\u002F2.rbac","i-lucide-users",{"title":220,"path":221,"stem":222,"icon":223},"Policies","\u002Fen\u002Fauth\u002Fpolicy","en\u002F06.auth\u002F3.policy","i-lucide-gavel",{"title":225,"path":226,"stem":227,"icon":228},"Using auth standalone","\u002Fen\u002Fauth\u002Fstandalone","en\u002F06.auth\u002F4.standalone","i-lucide-plug",{"title":230,"path":231,"stem":232,"icon":156},"Social login with goth, standalone","\u002Fen\u002Fauth\u002Fsocial-standalone","en\u002F06.auth\u002F5.social-standalone",{"title":234,"icon":235,"path":236,"stem":237,"children":238,"page":44},"dbx","i-lucide-database","\u002Fen\u002Fdbx","en\u002F07.dbx",[239,242,246,250,255],{"title":52,"path":240,"stem":241,"icon":235},"\u002Fen\u002Fdbx\u002Foverview","en\u002F07.dbx\u002F1.overview",{"title":243,"path":244,"stem":245,"icon":228},"pgx","\u002Fen\u002Fdbx\u002Fpg","en\u002F07.dbx\u002F2.pg",{"title":247,"path":248,"stem":249,"icon":183},"bun","\u002Fen\u002Fdbx\u002Fbunx","en\u002F07.dbx\u002F3.bunx",{"title":251,"path":252,"stem":253,"icon":254},"Transactions","\u002Fen\u002Fdbx\u002Ftransactions","en\u002F07.dbx\u002F4.transactions","i-lucide-git-merge",{"title":256,"path":257,"stem":258,"icon":79},"Seeders","\u002Fen\u002Fdbx\u002Fseed","en\u002F07.dbx\u002F5.seed",{"title":260,"icon":192,"path":261,"stem":262,"children":263,"page":44},"envconf","\u002Fen\u002Fenvconf","en\u002F08.envconf",[264,267],{"title":52,"path":265,"stem":266,"icon":192},"\u002Fen\u002Fenvconf\u002Foverview","en\u002F08.envconf\u002F1.overview",{"title":268,"path":269,"stem":270,"icon":192},"Recipes","\u002Fen\u002Fenvconf\u002Frecipes","en\u002F08.envconf\u002F2.recipes",{"title":272,"icon":188,"path":273,"stem":274,"children":275,"page":44},"errs","\u002Fen\u002Ferrs","en\u002F09.errs",[276,279,283],{"title":52,"path":277,"stem":278,"icon":188},"\u002Fen\u002Ferrs\u002Foverview","en\u002F09.errs\u002F1.overview",{"title":280,"path":281,"stem":282,"icon":188},"API","\u002Fen\u002Ferrs\u002Fapi","en\u002F09.errs\u002F2.api",{"title":284,"path":285,"stem":286,"icon":188},"Integration","\u002Fen\u002Ferrs\u002Fintegration","en\u002F09.errs\u002F3.integration",{"title":288,"icon":289,"path":290,"stem":291,"children":292,"page":44},"events","i-lucide-workflow","\u002Fen\u002Fevents","en\u002F10.events",[293,297,302],{"title":294,"path":295,"stem":296,"icon":146},"Events","\u002Fen\u002Fevents\u002Foverview","en\u002F10.events\u002F1.overview",{"title":298,"path":299,"stem":300,"icon":301},"Outbox","\u002Fen\u002Fevents\u002Foutbox","en\u002F10.events\u002F2.outbox","i-lucide-inbox",{"title":303,"path":304,"stem":305,"icon":306},"Scheduling","\u002Fen\u002Fevents\u002Fscheduler","en\u002F10.events\u002F3.scheduler","i-lucide-calendar-clock",{"title":308,"icon":309,"path":310,"stem":311,"children":312,"page":44},"httperr","i-lucide-globe","\u002Fen\u002Fhttperr","en\u002F11.httperr",[313,316,321],{"title":52,"path":314,"stem":315,"icon":309},"\u002Fen\u002Fhttperr\u002Foverview","en\u002F11.httperr\u002F1.overview",{"title":317,"path":318,"stem":319,"icon":320},"Error responses","\u002Fen\u002Fhttperr\u002Ferror-responses","en\u002F11.httperr\u002F2.error-responses","i-lucide-octagon-alert",{"title":322,"path":323,"stem":324,"icon":325},"Validation","\u002Fen\u002Fhttperr\u002Fvalidation","en\u002F11.httperr\u002F3.validation","i-lucide-badge-check",{"title":327,"icon":328,"path":329,"stem":330,"children":331,"page":44},"logx","i-lucide-scroll-text","\u002Fen\u002Flogx","en\u002F12.logx",[332,335],{"title":52,"path":333,"stem":334,"icon":328},"\u002Fen\u002Flogx\u002Foverview","en\u002F12.logx\u002F1.overview",{"title":336,"path":337,"stem":338,"icon":47},"Monolog formatter","\u002Fen\u002Flogx\u002Fmonolog","en\u002F12.logx\u002F2.monolog",{"title":340,"icon":341,"path":342,"stem":343,"children":344,"page":44},"mail","i-lucide-mail","\u002Fen\u002Fmail","en\u002F13.mail",[345,348,352],{"title":52,"path":346,"stem":347,"icon":341},"\u002Fen\u002Fmail\u002Foverview","en\u002F13.mail\u002F1.overview",{"title":349,"path":350,"stem":351,"icon":341},"SMTP","\u002Fen\u002Fmail\u002Fsmtp","en\u002F13.mail\u002F2.smtp",{"title":353,"path":354,"stem":355,"icon":341},"MJML","\u002Fen\u002Fmail\u002Fmjml","en\u002F13.mail\u002F3.mjml",{"title":357,"icon":358,"path":359,"stem":360,"children":361,"page":44},"notify","i-lucide-bell","\u002Fen\u002Fnotify","en\u002F14.notify",[362,365,369],{"title":52,"path":363,"stem":364,"icon":358},"\u002Fen\u002Fnotify\u002Foverview","en\u002F14.notify\u002F1.overview",{"title":366,"path":367,"stem":368,"icon":358},"Database channel","\u002Fen\u002Fnotify\u002Fdatabase","en\u002F14.notify\u002F2.database",{"title":370,"path":371,"stem":372,"icon":358},"Broadcast channel","\u002Fen\u002Fnotify\u002Fbroadcast","en\u002F14.notify\u002F3.broadcast",{"title":374,"icon":375,"path":376,"stem":377,"children":378,"page":44},"paginate","i-lucide-list-ordered","\u002Fen\u002Fpaginate","en\u002F15.paginate",[379,382],{"title":52,"path":380,"stem":381,"icon":375},"\u002Fen\u002Fpaginate\u002Foverview","en\u002F15.paginate\u002F1.overview",{"title":383,"path":384,"stem":385,"icon":39},"Cursor pagination","\u002Fen\u002Fpaginate\u002Fcursor","en\u002F15.paginate\u002F2.cursor",{"title":387,"icon":183,"path":388,"stem":389,"children":390,"page":44},"queue","\u002Fen\u002Fqueue","en\u002F16.queue",[391,394],{"title":52,"path":392,"stem":393,"icon":375},"\u002Fen\u002Fqueue\u002Foverview","en\u002F16.queue\u002F1.overview",{"title":395,"path":396,"stem":397,"icon":183},"Tasks","\u002Fen\u002Fqueue\u002Ftasks","en\u002F16.queue\u002F2.tasks",{"title":399,"icon":400,"path":401,"stem":402,"children":403,"page":44},"storage","i-lucide-hard-drive","\u002Fen\u002Fstorage","en\u002F17.storage",[404,407,411,415,420],{"title":52,"path":405,"stem":406,"icon":400},"\u002Fen\u002Fstorage\u002Foverview","en\u002F17.storage\u002F1.overview",{"title":408,"path":409,"stem":410,"icon":400},"Disk API","\u002Fen\u002Fstorage\u002Fdisk-api","en\u002F17.storage\u002F2.disk-api",{"title":412,"path":413,"stem":414,"icon":400},"Memory and local disk","\u002Fen\u002Fstorage\u002Flocal","en\u002F17.storage\u002F3.local",{"title":416,"path":417,"stem":418,"icon":419},"S3","\u002Fen\u002Fstorage\u002Fs3","en\u002F17.storage\u002F4.s3","i-lucide-cloud",{"title":421,"path":422,"stem":423,"icon":424},"Testing","\u002Fen\u002Fstorage\u002Ftesting","en\u002F17.storage\u002F5.testing","i-lucide-flask-conical",{"title":426,"icon":427,"path":428,"stem":429,"children":430,"page":44},"telemetry","i-lucide-activity","\u002Fen\u002Ftelemetry","en\u002F18.telemetry",[431,434,438,443],{"title":52,"path":432,"stem":433,"icon":427},"\u002Fen\u002Ftelemetry\u002Foverview","en\u002F18.telemetry\u002F1.overview",{"title":435,"path":436,"stem":437,"icon":328},"Logging","\u002Fen\u002Ftelemetry\u002Flogging","en\u002F18.telemetry\u002F2.logging",{"title":439,"path":440,"stem":441,"icon":442},"OpenTelemetry","\u002Fen\u002Ftelemetry\u002Fopentelemetry","en\u002F18.telemetry\u002F3.opentelemetry","i-lucide-radar",{"title":444,"path":445,"stem":446,"icon":447},"Sentry","\u002Fen\u002Ftelemetry\u002Fsentry","en\u002F18.telemetry\u002F4.sentry","i-lucide-bug",{"id":449,"title":336,"body":450,"description":1340,"extension":1341,"links":1342,"meta":1343,"navigation":1344,"path":337,"seo":1345,"stem":338,"__hash__":1346},"docs_en\u002Fen\u002F12.logx\u002F2.monolog.md",{"type":451,"value":452,"toc":1332},"minimark",[453,473,478,496,506,512,518,521,603,607,610,701,721,773,777,803,1063,1073,1077,1109,1116,1120,1127,1292,1296,1328],[454,455,456,457,461,462,465,466,469,470,472],"p",{},"In Go, the first cold shower is often logging: the raw ",[458,459,460],"code",{},"log"," package's one-line, context-free output, or a structured logger's wall of ",[458,463,464],{},"key=value"," where a stack trace collapses into a single escaped string. ",[458,467,468],{},"logx\u002Fmonolog"," is ",[458,471,327],{},"'s answer for development: a console handler that, set as the active format, looks exactly like what you know from PHP.",[474,475,477],"h2",{"id":476},"what-it-looks-like","What it looks like",[454,479,480,481,484,485,488,489,492,493,495],{},"Set ",[458,482,483],{},"Format: \"monolog\""," on ",[458,486,487],{},"logx.Config"," (or ",[458,490,491],{},"LOG_FORMAT=monolog",", if ",[458,494,487],{}," is loaded from the environment) and the console reads like this:",[497,498,504],"pre",{"className":499,"code":501,"language":502,"meta":503},[500],"language-text","[2026-07-15 10:23:44] shop.INFO: order placed {\"order_id\":\"o_8412\",\"total\":12990}\n[2026-07-15 10:23:45] shop.WARNING: payment provider slow, retrying {\"attempt\":2,\"provider\":\"stripe\"} in \u002Fhome\u002Fyou\u002Fshop\u002Finternal\u002Fmodules\u002Fshop\u002Fsurfaces\u002Fapi\u002Fservice\u002Fpayments.go:114\n","text","",[458,505,501],{"__ignoreMap":503},[454,507,508,509,511],{},"And when a wrapped ",[458,510,272],{}," error reaches the logger:",[497,513,516],{"className":514,"code":515,"language":502,"meta":503},[500],"[2026-07-15 10:23:46] shop.ERROR: request failed: shop_out_of_stock: shop: place order: inventory: decrement: insufficient stock {\"code\":\"shop_out_of_stock\",\"method\":\"POST\",\"path\":\"\u002Fapi\u002Fv1\u002Fshop\u002Forders\",\"status\":500}\nStack trace:\n#0 \u002Fhome\u002Fyou\u002Fshop\u002Finternal\u002Fmodules\u002Fshop\u002Frepository\u002Finventory.go(87): repository.(*InventoryRepository).Decrement()\n#1 \u002Fhome\u002Fyou\u002Fshop\u002Finternal\u002Fmodules\u002Fshop\u002Forders.go(41): shop.(*Service).PlaceOrder()\n#2 \u002Fhome\u002Fyou\u002Fshop\u002Finternal\u002Fmodules\u002Fshop\u002Fsurfaces\u002Fapi\u002Fservice\u002Forders.go(52): service.(*OrderService).PlaceOrder()\n#3 \u002Fhome\u002Fyou\u002Fshop\u002Finternal\u002Fmodules\u002Fshop\u002Fsurfaces\u002Fapi\u002Fhttp\u002Fhandlers.go(61): http.(*Handler).PlaceOrder()\n#4 {main}\n",[458,517,515],{"__ignoreMap":503},[454,519,520],{},"What's at work in these few lines:",[522,523,524,540,553,563,573,587],"ul",{},[525,526,527,531,532,535,536,539],"li",{},[528,529,530],"strong",{},"The channel names the record's source"," (a service name, typically), so running several services' logs side by side, you can still see who is talking. The ",[458,533,534],{},"WARN"," level renders Monolog-faithfully as ",[458,537,538],{},"WARNING",".",[525,541,542,548,549,552],{},[528,543,544,545,547],{},"The error headline leads with the ",[458,546,272],{}," code"," (",[458,550,551],{},"shop_out_of_stock: ...","), so the failure mode is identifiable without reading the JSON tail; the code also appears in the JSON context.",[525,554,555,558,559,562],{},[528,556,557],{},"The stack trace is complete, with absolute paths",": most terminals and editors make them clickable. Frames run from the error's point of origin upward; frames from dependencies (the Go module cache) are dimmed, and the runtime entry frames are replaced by the terminal ",[458,560,561],{},"{main}"," line.",[525,564,565,568,569,572],{},[528,566,567],{},"The error attr is not duplicated",": the value of ",[458,570,571],{},"slog.Any(\"error\", err)"," goes into the headline and the stack block and is excluded from the JSON context.",[525,574,575,578,579,582,583,586],{},[528,576,577],{},"Color only on a terminal",": ",[458,580,581],{},"NO_COLOR"," and ",[458,584,585],{},"TERM=dumb"," are honored; piped output carries no escape garbage.",[525,588,589,590,592,593,596,597,599,600,539],{},"A ",[458,591,534],{},"\u002F",[458,594,595],{},"ERROR"," record without an ",[458,598,272],{}," stack still gets a location: its call site is appended as ",[458,601,602],{}," in file:line",[474,604,606],{"id":605},"logxmonolog-up-close","logx\u002Fmonolog up close",[454,608,609],{},"The format driver is a standalone package with a single constructor:",[497,611,615],{"className":612,"code":613,"language":614,"meta":503,"style":503},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import \"github.com\u002Fgp-system\u002Flogx\u002Fmonolog\"\n\nfunc NewHandler(w io.Writer, level slog.Level, channel string) *Handler\n","go",[458,616,617,637,644],{"__ignoreMap":503},[618,619,622,626,630,634],"span",{"class":620,"line":621},"line",1,[618,623,625],{"class":624},"s7zQu","import",[618,627,629],{"class":628},"sMK4o"," \"",[618,631,633],{"class":632},"sBMFI","github.com\u002Fgp-system\u002Flogx\u002Fmonolog",[618,635,636],{"class":628},"\"\n",[618,638,640],{"class":620,"line":639},2,[618,641,643],{"emptyLinePlaceholder":642},true,"\n",[618,645,647,650,654,657,661,664,666,669,672,675,678,680,683,685,688,692,695,698],{"class":620,"line":646},3,[618,648,649],{"class":628},"func",[618,651,653],{"class":652},"s2Zo4"," NewHandler",[618,655,656],{"class":628},"(",[618,658,660],{"class":659},"sHdIc","w",[618,662,663],{"class":632}," io",[618,665,539],{"class":628},[618,667,668],{"class":632},"Writer",[618,670,671],{"class":628},",",[618,673,674],{"class":659}," level",[618,676,677],{"class":632}," slog",[618,679,539],{"class":628},[618,681,682],{"class":632},"Level",[618,684,671],{"class":628},[618,686,687],{"class":659}," channel",[618,689,691],{"class":690},"spNyl"," string",[618,693,694],{"class":628},")",[618,696,697],{"class":628}," *",[618,699,700],{"class":632},"Handler\n",[454,702,703,706,707,469,710,713,714,717,718,720],{},[458,704,705],{},"logx.ConsoleHandler"," returns this when ",[458,708,709],{},"Config.Format",[458,711,712],{},"\"monolog\"",", but you can wire it anywhere a ",[458,715,716],{},"slog.Handler"," is expected, with or without the rest of ",[458,719,327],{},". Worth knowing:",[522,722,723,745,767],{},[525,724,725,732,733,736,737,740,741,744],{},[528,726,727,728,731],{},"It is ",[458,729,730],{},"slog","-native."," ",[458,734,735],{},"With(...)"," attrs and ",[458,738,739],{},"WithGroup(...)"," groups render correctly, as nested JSON in the context part (",[458,742,743],{},"\"req\":{\"status\":200}",").",[525,746,747,752,753,758,759,762,763,766],{},[528,748,749,750,539],{},"Stacks come from ",[458,751,272],{}," The handler pulls out the record's first error-valued attr; if it (or anything in its wrap chain) is an ",[754,755,756],"a",{"href":277},[458,757,272],{}," error, its full-path stack from ",[458,760,761],{},"errs.FullFrames"," is rendered. A plain ",[458,764,765],{},"errors.New"," error gets no stack block: the log call site goes on the line instead.",[525,768,769,772],{},[528,770,771],{},"Lines stay atomic under concurrency",": the handler's clones share a mutex for writes; there are no torn lines.",[474,774,776],{"id":775},"structured-errors-in-logs-none-of-this-without-errs","Structured errors in logs: none of this without errs",[454,778,779,780,784,785,788,789,792,793,796,797,799,800,802],{},"The stack traces above are mined from ",[754,781,782],{"href":277},[458,783,272],{}," errors, and that is not a console privilege: ",[458,786,787],{},"*errs.Error"," implements ",[458,790,791],{},"slog.LogValuer",", so in ",[528,794,795],{},"any"," structured ",[458,798,716],{},", not only ",[458,801,468],{},", the error unfolds as a group:",[497,804,808],{"className":805,"code":806,"language":807,"meta":503,"style":503},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\"error\": {\n  \"msg\": \"shop: place order: inventory: decrement: insufficient stock\",\n  \"code\": \"shop_out_of_stock\",\n  \"public\": \"One or more items are out of stock.\",\n  \"chain\": [ { \"msg\": \"shop: place order\", \"file\": \"service\u002Forders.go\", \"line\": 52, \"...\" : \"…\" }, \"…\" ],\n  \"stack\": [ { \"file\": \"repository\u002Finventory.go\", \"line\": 87, \"...\" : \"…\" }, \"…\" ]\n}\n","json",[458,809,810,827,850,869,890,986,1057],{"__ignoreMap":503},[618,811,812,815,819,821,824],{"class":620,"line":621},[618,813,814],{"class":628},"\"",[618,816,818],{"class":817},"sfazB","error",[618,820,814],{"class":628},[618,822,578],{"class":823},"sTEyZ",[618,825,826],{"class":628},"{\n",[618,828,829,832,835,837,840,842,845,847],{"class":620,"line":639},[618,830,831],{"class":628},"  \"",[618,833,834],{"class":690},"msg",[618,836,814],{"class":628},[618,838,839],{"class":628},":",[618,841,629],{"class":628},[618,843,844],{"class":817},"shop: place order: inventory: decrement: insufficient stock",[618,846,814],{"class":628},[618,848,849],{"class":628},",\n",[618,851,852,854,856,858,860,862,865,867],{"class":620,"line":646},[618,853,831],{"class":628},[618,855,458],{"class":690},[618,857,814],{"class":628},[618,859,839],{"class":628},[618,861,629],{"class":628},[618,863,864],{"class":817},"shop_out_of_stock",[618,866,814],{"class":628},[618,868,849],{"class":628},[618,870,872,874,877,879,881,883,886,888],{"class":620,"line":871},4,[618,873,831],{"class":628},[618,875,876],{"class":690},"public",[618,878,814],{"class":628},[618,880,839],{"class":628},[618,882,629],{"class":628},[618,884,885],{"class":817},"One or more items are out of stock.",[618,887,814],{"class":628},[618,889,849],{"class":628},[618,891,893,895,898,900,902,905,908,910,912,914,916,918,921,923,925,927,930,932,934,936,939,941,943,945,947,949,951,955,957,959,962,964,967,969,972,974,977,979,981,983],{"class":620,"line":892},5,[618,894,831],{"class":628},[618,896,897],{"class":690},"chain",[618,899,814],{"class":628},[618,901,839],{"class":628},[618,903,904],{"class":628}," [",[618,906,907],{"class":628}," {",[618,909,629],{"class":628},[618,911,834],{"class":632},[618,913,814],{"class":628},[618,915,839],{"class":628},[618,917,629],{"class":628},[618,919,920],{"class":817},"shop: place order",[618,922,814],{"class":628},[618,924,671],{"class":628},[618,926,629],{"class":628},[618,928,929],{"class":632},"file",[618,931,814],{"class":628},[618,933,839],{"class":628},[618,935,629],{"class":628},[618,937,938],{"class":817},"service\u002Forders.go",[618,940,814],{"class":628},[618,942,671],{"class":628},[618,944,629],{"class":628},[618,946,620],{"class":632},[618,948,814],{"class":628},[618,950,839],{"class":628},[618,952,954],{"class":953},"sbssI"," 52",[618,956,671],{"class":628},[618,958,629],{"class":628},[618,960,961],{"class":632},"...",[618,963,814],{"class":628},[618,965,966],{"class":628}," :",[618,968,629],{"class":628},[618,970,971],{"class":817},"…",[618,973,814],{"class":628},[618,975,976],{"class":628}," },",[618,978,629],{"class":628},[618,980,971],{"class":817},[618,982,814],{"class":628},[618,984,985],{"class":628}," ],\n",[618,987,989,991,994,996,998,1000,1002,1004,1006,1008,1010,1012,1015,1017,1019,1021,1023,1025,1027,1030,1032,1034,1036,1038,1040,1042,1044,1046,1048,1050,1052,1054],{"class":620,"line":988},6,[618,990,831],{"class":628},[618,992,993],{"class":690},"stack",[618,995,814],{"class":628},[618,997,839],{"class":628},[618,999,904],{"class":628},[618,1001,907],{"class":628},[618,1003,629],{"class":628},[618,1005,929],{"class":632},[618,1007,814],{"class":628},[618,1009,839],{"class":628},[618,1011,629],{"class":628},[618,1013,1014],{"class":817},"repository\u002Finventory.go",[618,1016,814],{"class":628},[618,1018,671],{"class":628},[618,1020,629],{"class":628},[618,1022,620],{"class":632},[618,1024,814],{"class":628},[618,1026,839],{"class":628},[618,1028,1029],{"class":953}," 87",[618,1031,671],{"class":628},[618,1033,629],{"class":628},[618,1035,961],{"class":632},[618,1037,814],{"class":628},[618,1039,966],{"class":628},[618,1041,629],{"class":628},[618,1043,971],{"class":817},[618,1045,814],{"class":628},[618,1047,976],{"class":628},[618,1049,629],{"class":628},[618,1051,971],{"class":817},[618,1053,814],{"class":628},[618,1055,1056],{"class":628}," ]\n",[618,1058,1060],{"class":620,"line":1059},7,[618,1061,1062],{"class":628},"}\n",[454,1064,1065,1066,1069,1070,539],{},"So the same error is a PHP-style stack trace on the dev console, and machine-ready JSON in any other handler you fan it out to (the framework's OTel log bridge and Sentry handler among them, see ",[754,1067,1068],{"href":436},"Telemetry: Logging","), all from a single ",[458,1071,1072],{},"return err",[474,1074,1076],{"id":1075},"where-did-the-file-logs-go","Where did the file logs go?",[454,1078,1079,1080,592,1083,1086,1087,1089,1090,1093,1094,1097,1098,1104,1105,1108],{},"Nowhere, deliberately: there is no ",[458,1081,1082],{},"single",[458,1084,1085],{},"daily"," file driver here, ",[458,1088,468],{}," writes to whatever ",[458,1091,1092],{},"io.Writer"," you give ",[458,1095,1096],{},"NewHandler",", typically stdout. This follows the ",[754,1099,1103],{"href":1100,"rel":1101},"https:\u002F\u002F12factor.net\u002Flogs",[1102],"nofollow","12-factor"," principle: logs go to ",[528,1106,1107],{},"stdout as an event stream",", and collection, rotation and retention are the platform's job, not the logger's. In a container the runtime captures stdout anyway; a collector, or a plain shell redirect, takes it from there.",[454,1110,1111,1112,1115],{},"If you still want a local file: ",[458,1113,1114],{},"go run .\u002Fcmd\u002Fmyapp 2>&1 | tee myapp.log","; in a pipe the handler automatically writes without colors.",[474,1117,1119],{"id":1118},"monolog-concepts-mapped","Monolog concepts, mapped",[454,1121,1122,1123,1126],{},"If you arrive from ",[458,1124,1125],{},"config\u002Flogging.php",", this is how the concepts map:",[1128,1129,1130,1146],"table",{},[1131,1132,1133],"thead",{},[1134,1135,1136,1140,1143],"tr",{},[1137,1138,1139],"th",{},"Monolog",[1137,1141,1142],{},"gpsystem",[1137,1144,1145],{},"Where",[1147,1148,1149,1175,1192,1210,1226,1250,1265,1279],"tbody",{},[1134,1150,1151,1155,1168],{},[1152,1153,1154],"td",{},"channel name",[1152,1156,1157,1158,1161,1162,1164,1165,694],{},"whatever ",[458,1159,1160],{},"channel"," you pass ",[458,1163,1096],{}," (the framework uses ",[458,1166,1167],{},"OTEL_SERVICE_NAME",[1152,1169,1170,1171,1174],{},"the ",[458,1172,1173],{},"shop.INFO"," part of the monolog line",[1134,1176,1177,1182,1187],{},[1152,1178,1179,1181],{},[458,1180,993],{}," driver (several channels in one)",[1152,1183,1184],{},[458,1185,1186],{},"logx.Fanout",[1152,1188,1189],{},[754,1190,1191],{"href":333},"logx: Overview",[1134,1193,1194,1201,1206],{},[1152,1195,1196,1197,1200],{},"a channel's ",[458,1198,1199],{},"level"," threshold",[1152,1202,1203],{},[458,1204,1205],{},"logx.LevelFilter",[1152,1207,1208],{},[754,1209,1191],{"href":333},[1134,1211,1212,1220,1223],{},[1152,1213,1214,1216,1217,1219],{},[458,1215,1082],{}," \u002F ",[458,1218,1085],{}," file driver",[1152,1221,1222],{},"none (stdout is the only destination)",[1152,1224,1225],{},"see above",[1134,1227,1228,1235,1246],{},[1152,1229,1230,1231,1234],{},"formatter (",[458,1232,1233],{},"LineFormatter",", JSON)",[1152,1236,1237,548,1240,1216,1243,694],{},[458,1238,1239],{},"logx.Config.Format",[458,1241,1242],{},"auto",[458,1244,1245],{},"monolog",[1152,1247,1248],{},[754,1249,1191],{"href":333},[1134,1251,1252,1257,1262],{},[1152,1253,1254],{},[458,1255,1256],{},"Log::info('msg', ['ctx' => ...])",[1152,1258,1259],{},[458,1260,1261],{},"slog.InfoContext(ctx, \"msg\", slog.Any(\"ctx\", ...))",[1152,1263,1264],{},"app code",[1134,1266,1267,1272,1277],{},[1152,1268,1269],{},[458,1270,1271],{},"Log::withContext([...])",[1152,1273,1274],{},[458,1275,1276],{},"logger := slog.Default().With(...)",[1152,1278,1264],{},[1134,1280,1281,1284,1287],{},[1152,1282,1283],{},"a Sentry \u002F Slack channel in the stack",[1152,1285,1286],{},"another handler added to the fanout",[1152,1288,1289,1290],{},"your own wiring, or the framework's fanout, see ",[754,1291,1068],{"href":436},[474,1293,1295],{"id":1294},"related-pages","Related pages",[522,1297,1298,1317,1323],{},[525,1299,1300,1302,1303,1306,1307,592,1310,592,1313,1316],{},[754,1301,1191],{"href":333},": install, ",[458,1304,1305],{},"Config",", and the ",[458,1308,1309],{},"ConsoleHandler",[458,1311,1312],{},"LevelFilter",[458,1314,1315],{},"Fanout"," composition this formatter plugs into.",[525,1318,1319,1322],{},[754,1320,1321],{"href":277},"errs: Overview",": the error type this formatter's stack traces come from.",[525,1324,1325,1327],{},[754,1326,1068],{"href":436},": how the framework fans this handler out alongside the OTel log bridge and the Sentry capture handler.",[1329,1330,1331],"style",{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":503,"searchDepth":639,"depth":639,"links":1333},[1334,1335,1336,1337,1338,1339],{"id":476,"depth":639,"text":477},{"id":605,"depth":639,"text":606},{"id":775,"depth":639,"text":776},{"id":1075,"depth":639,"text":1076},{"id":1118,"depth":639,"text":1119},{"id":1294,"depth":639,"text":1295},"A PHP\u002FMonolog-style console formatter, with full-path stack traces pulled out of an errs error.","md",null,{},{"icon":47},{"title":336,"description":1340},"7Xidk84jw_XZ9TU7eooo8suniRCEYcoOEe0gP_fhQrU",[1348,1350],{"title":52,"path":333,"stem":334,"description":1349,"icon":328,"children":-1},"A standalone slog composition (console format, level filtering, fanout) plus a PHP\u002FMonolog-style console formatter.",{"title":52,"path":346,"stem":347,"description":1351,"icon":341,"children":-1},"Email sending: fluent Message builder, MJML templates, a memory mailer for tests.",1787346799873]