LogTape 2.3.0: Scoped configuration, failure-only test logs, and GraphQL Yoga #197
dahlia
announced in
Announcements
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
LogTape is a logging library for JavaScript and TypeScript that works across Deno, Node.js, Bun, and browsers. It's built around structured logging, has zero dependencies, and is designed to work as well in library code as in application code.
Version 2.3.0 adds scoped configuration for temporary logging policies, a failure log reporter with dedicated packages for four test runners, a GraphQL Yoga integration, and finer control over what the Sentry sink reports. Here's what changed.
Scoped configuration
configure()sets logging policy for the whole process, which fits an application entry point but is awkward for temporary behavior inside one execution flow. A test helper that wants a buffering sink for one test case, or a request handler that wants verbose output for one request, previously had no way to do that without mutating the same global logger tree every other concurrent test or request also depends on.The new
withConfig()installs aScopedConfigfor the duration of a callback, reusing thecontextLocalStorageyou already pass toconfigure():The scoped configuration is a full override, not a merge: sinks and filters from the process-wide configuration aren't inherited, so a scope that wants meta logs configures them itself. Nested
withConfig()calls restore the outer scope on exit, and sinks or filters created for a scope are disposed once its callback settles.withConfig()requiresConfig.contextLocalStorageto already be set; without it, it throws aConfigErrorrather than falling back silently.withConfigSync()is the synchronous counterpart, and it rejects callbacks that return a promise.See the scoped configuration documentation for the full lifetime and nesting rules. (#185, #188)
Failure log reporter
@logtape/testingnow shipscreateFailureLogReporter(). It buffers log records while a wrapped callback runs, discards them if the callback passes, and reports them to a sink if it throws or rejects, so a passing test suite stays quiet while a failing one still shows what led up to the failure:The reporter is built on scoped configuration, so it doesn't call
configure()orreset()around each test and doesn't touch process-wide routing while a test runs; it still requires the process-wide configuration to provideConfig.contextLocalStorage.wrap()preserves whatever parameters the test runner passes to the callback (a test context, fixtures) and always returns an async function.run()invokes the callback directly for callers that don't go through a test runner'swrap()-style API.The default mode is
on-failure. Setmode: "always"to see buffered logs even for passing tests, ormode: "never"to keep a shared wrapper in place while suppressing output.sinkandformattercustomize where and how reports are written, andgetFailureLogReporterOptionsFromEnv()parsesLOGTAPE_TEST_MODEandLOGTAPE_TEST_LOWEST_LEVELthrough a runtime-specific environment reader. The recorder API now also has its own@logtape/testing/recorderentry point alongside the new@logtape/testing/reporter; the root@logtape/testingexport still re-exports both for compatibility. (#186, #190)Runner-aware testing packages
Wrapping every test callback with
reporter.wrap()by hand works, but it's tedious across a large suite. Four new packages adapt the reporter to the runner you're already using:@logtape/testing-node,@logtape/testing-deno,@logtape/testing-bun, and@logtape/testing-vitest.Each package exports a wrapped
test(and, where the runner has one,it) that behaves like the runner's own. The Node.js integration, for example:The
autoloadentry point configures the minimalcontextLocalStoragethe reporter needs when LogTape hasn't been configured yet. If your suite already configures LogTape, that configuration must includecontextLocalStorage, or autoload throws instead of silently overriding it. Each package also exportscreateTest()(and@logtape/testing-vitestacreateVitest()) for settinglowestLevel,mode,sink, orformatterexplicitly.Runner-specific features carry through unchanged:
test.only(),test.skip(), andtest.todo()on Node.js;test.each()and wrappedTestContext.step()on Deno; Bun's shorthand helpers and callback-style tests; and Vitest'stest.each(),test.for(),test.extend(), and fixture callbacks. (#187, #191)New package: @logtape/graphql-yoga
@logtape/graphql-yogais a new package that lets GraphQL Yoga use LogTape as its logging backend through Yoga'screateYoga({ logging })option:Yoga's logger methods take arbitrary arguments; the adapter treats a leading string as the message, a leading plain object as structured properties, and a leading
Erroras LogTape's error-aware logging path, keeping any remaining arguments under anargsproperty instead of flattening or stringifying them. The default level mapping (debugtodebug,infotoinfo,warntowarning,errortoerror) can be overridden withYogaLoggerOptions.levelsMap. (#184)@logtape/sentry: Error properties and level routing
The Sentry sink decides whether to call
captureException()by checking anerroror, failing that, a Pino-styleerrproperty for anErrorvalue. The newerrorPropertyNamesoption onSentrySinkOptionslets you replace that list for logging conventions that use a different property name; the default remains["error", "err"]. Thanks to @matthiasfeist for the issue report that started this. (#189)Until now, the sink also had only one filter point ahead of every output path, so there was no way to keep verbose records as breadcrumbs while sending only
warningand above through Sentry's Logs API:withFilter()drops records before the sink ever sees them, so they never become breadcrumbs either. The newlogsandbreadcrumbsoptions route by level after the sink has accepted a record:With this configuration,
trace,debug, andinforecords become breadcrumbs, whilewarning,error, andfatalrecords are also sent through Sentry's Logs API;errorandfatalrecords still create Sentry Issues as before, independent of this routing.breadcrumbs: truetakes over whatenableBreadcrumbs: trueused to do;enableBreadcrumbsstill works but is deprecated.beforeSendis unchanged and still applies to every output path ahead of this routing. Thanks to @sebws for reporting the gap and sketching the shape of the fix. (#193, #194)Agent skill: install straight from the repository
The LogTape Agent Skill has been available through the
@logtape/logtapenpm package since 2.1.0. It can now also be installed directly from this repository withnpx skills add dahlia/logtape, and the repository can be added as a Claude Code plugin marketplace for teams that manage skills that way.Upgrading
There are no breaking changes in 2.3.0. See the full changelog for complete details.
All reactions