Repository navigation
feat(plugin-logger): rework the sentry, evlog and winston transports - #232
Conversation
Derive a shared `message`, `error` and `context` on every log payload, so each transport reads an entry the same way instead of guessing, and rebuild the transports on top of them. - SentryTransport keeps the message and context next to an exception, can record breadcrumbs and send Sentry Logs, and flushes the client on close. The `@sentry/node` peer dependency is dropped. - EvlogTransport writes structured events through evlog's pipeline and maps all six levels. A new `@wolfstar/plugin-logger/evlog/plugin` entry runs `initLogger`, wraps the drain in evlog's pipeline on request, and emits one wide event per interaction, enrichable with `useInteractionLogger()`. The Stars module gains an `evlog` option. - WinstonTransport serialises errors, flags `fatal` entries and no longer hangs when closed twice. - Add tests for the consola, evlog and winston adapters.
|
Note This drawing shows
1 finding · reviewed 🟠 Sentry close treats a timed out flush as complete ·
|
There was a problem hiding this comment.
ℹ️ No critical issues — two minor suggestions inline.
Reviewed changes
Reviewed the full single commit. I also ran pnpm vitest run packages/plugin-logger tests/module-entries.test.ts locally; all 159 tests pass.
- Payload —
createLogPayloadderivesmessage,errorandcontextlazily and memoises them, so every transport reads an entry the same way. - Sentry — message and context are kept in
extra, with opt-in breadcrumbs and Sentry Logs, a flush on close, and no@sentry/nodepeer. - evlog transport — entries become structured events across all six levels, and the drain is flushed on close.
- evlog plugin —
@wolfstar/plugin-logger/evlog/pluginrunsinitLogger, optionally wraps the drain in a pipeline, and emits one wide event per interaction. I checked thecommandRuntocommandFinishpairing against framework 6.1.1; it is emitted from the same async function, so theenterWithapproach holds. - Stars module — the
evlogoption registers the evlog plugin before the logger plugin and resolves the drain file againstctx.root. - winston — errors are serialised,
fatalentries are flagged, andclose()is idempotent.
claude-sonnet-5-5 | 𝕏
The Stars module typed its `evlog` option with the evlog plugin's options, which come from evlog's own types. `evlog` is an optional peer, so a consumer of `./module` without it got unresolved imports in `module.d.ts` when `skipLibCheck` is off. Declare the options structurally in `module.ts`, and check at compile time (`assertions.ts`) that they stay assignable to the evlog plugin's. Also replace the interactions README snippet, which was not valid TypeScript.
@wolfstar/plugin-api
@wolfstar/plugin-broker
@wolfstar/plugin-cache
@wolfstar/plugin-gateway
@wolfstar/plugin-i18next
@wolfstar/plugin-logger
@wolfstar/plugin-scheduled-tasks
@wolfstar/plugin-sharder
@wolfstar/plugin-subcommands-advanced
commit: |
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
Reviewed the delta since the prior review (3373013). Both earlier threads are addressed and resolved. pnpm vitest run packages/plugin-logger tests/module-entries.test.ts passes (139 tests), and typecheck reports nothing in plugin-logger.
- Structural module options —
module.tsdeclaresEvlogModuleOptionswithout importing fromevlogor./evlog-plugin, somodule.d.tsresolves for consumers without the optionalevlogpeer. - Compile-time guard —
src/assertions.tsasserts thatEvlogModuleOptions(minusdrain) stays assignable to the evlog plugin'sEvlogInlineOptions. It is not an entrypoint. - Regression test —
module.test.tschecks the module source imports nothing from evlog or the evlog plugin. - README — the
interactionsexample is now two plain config objects.
claude-sonnet-5-5 | 𝕏
`src/assertions.ts` only holds a compile-time check that the Stars module's structural evlog options stay assignable to the evlog plugin's. Nothing imports it, so knip reported it as an unused file and failed the unused code check. Declare it as an entry, like the type-level tests of the other packages.

🔗 Linked issue
No linked issue.
🧭 Context
The Sentry, evlog and winston transports of
@wolfstar/plugin-loggereach guessed on their own what the logged values meant, and lost information doing it:Errorwas passed, and flattened everything to a string, so nothing went through evlog's drain pipeline as a structured event.extra.values, had no breadcrumbs or Sentry Logs, and never flushed on close.[object Object]for a non-string first value, serialised errors as{}, and hung whenclose()ran twice.📚 Description
Every
LogPayloadnow carries amessage, anerrorand acontext, derived once (and lazily) from the rawvalues. The transports are rebuilt on top of them.evlog is treated as the ecosystem it is rather than as another console:
EvlogTransporthands entries to evlog as structured events, and a new@wolfstar/plugin-logger/evlog/pluginentry runsinitLogger, wraps the drain in evlog's drain pipeline on request, and follows the client's interaction lifecycle to emit one wide event per interaction, as described in evlog's custom framework guide. The Stars module gets anevlogoption for it.I checked the evlog behaviour (drain shape, error serialisation,
createRequestLogger) against evlog 2.30.1 before relying on it, and the interaction events against the framework's emit sites and its synchronousAsyncEventEmitter. The interaction tests emit the client events with stub contexts rather than sending a signed request throughClient#fetch.Key changes
valuesonlymessage,error,context;createLogPayload()for custom transports and testsextra.values, no flush,@sentry/nodepeerextra, opt-inbreadcrumbLevelandlogLevel(Sentry Logs), flush on close, no Sentry peerError, flattened to a string,fatalandtracecollapsedevlogpeer raised to^2.30.0evlogPlugin,defineEvlogDrain,pipelineoption, one wide event per interaction,useInteractionLogger()evlog: trueor inline evlog options, withdrainpointing to a file default-exportingdefineEvlogDrain(...)[object Object], errors as{},close()could hangfatal: trueflag,close()is idempotentinteractionsis on by default for commands, components and modals once the evlog plugin is used; autocomplete is off because Discord sends a request per keystroke.Type of Change
The breaking part is the transports' output (Sentry
extra, evlog events), the raisedevlogpeer and the dropped@sentry/nodepeer. The package is on 0.x, so the changeset is a minor bump.Pre-flight Checklist
pnpm changeset(orpnpm changeset add --emptyif no release is needed). See .changeset/README.md.pnpm typecheckreports 146 errors locally, none inplugin-logger; I did not check whether they predate this branch.