Scoped logging configuration - #188
Conversation
Add withConfig(), withConfigSync(), and ScopedConfig for applying a LogTape configuration to the current execution context. Scoped configs use context-local storage, support nesting and concurrent scopes, dispose scoped resources on exit, and guard process-wide state changes while any scope is active. Update logger dispatch so active scopes override global routing without breaking context properties, category prefixes, lazy evaluation, filters, parent sinks, or lowestLevel: null semantics. The synchronous variant rejects async resources and promise-returning callbacks. Document the new behavior and add regression coverage for disposal, concurrency, nested scopes, invalid configuration, and async propagation edge cases. Fixes #185 #188 Assisted-by: Codex:gpt-5.5
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #188 +/- ##
==========================================
+ Coverage 84.72% 84.92% +0.19%
==========================================
Files 64 66 +2
Lines 11754 12578 +824
Branches 2667 2865 +198
==========================================
+ Hits 9959 10682 +723
- Misses 1304 1370 +66
- Partials 491 526 +35 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
@codex review |
There was a problem hiding this comment.
Code Review
This pull request introduces scoped configuration support to LogTape, allowing configurations to be applied temporarily within a specific execution context via withConfig() and withConfigSync(). The changes include the addition of the ScopedConfig type, the implementation of scoped configuration compilation and disposal in a new scoped-config.ts file, and updates to documentation and tests. Feedback on the changes suggests grouping and sorting imports in the test file alphabetically with the module under test last, and removing a redundant explicit type annotation for snapshotFailed in logger.ts.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 68821ae3ce
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Block new scoped configurations while process-wide configuration is being reset, disposed, or replaced. This keeps scopes from capturing a context-local storage that a concurrent global mutation is about to clear. Use internal disposal helpers for process exit and unload hooks so global resources can still be finalized while scoped configurations are active. Also keep the config test imports in the project order and remove a redundant local type annotation. #188 (comment) #188 (comment) #188 (comment) #188 (comment) Assisted-by: Codex:gpt-5.5
|
/gemini review |
|
@codex review |
There was a problem hiding this comment.
Code Review
This pull request introduces scoped configuration support to LogTape, allowing users to temporarily override process-wide logging policies within specific execution contexts using withConfig() and withConfigSync(). The implementation includes the new ScopedConfig type, context-local storage integration, automatic resource disposal, and comprehensive unit tests. The review feedback highlights critical safety improvements in scoped-config.ts, specifically recommending input validation at the start of configuration compilation and adding type guards before using the in operator on sinks and filters to prevent unhandled runtime TypeErrors when dealing with primitive values.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
|
Codex Review: Didn't find any major issues. You're on a roll. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Reject malformed scoped configuration objects before compiling their logger graph. This turns runtime-only mistakes from JavaScript callers or casts into ConfigError values instead of leaking TypeError from property access or the in operator. Also validate referenced sink and filter values before storing them in the compiled scope, and skip primitive unreferenced resources while collecting scoped disposables. #188 (comment) #188 (comment) #188 (comment) Assisted-by: Codex:gpt-5.5
|
@codex review |
There was a problem hiding this comment.
Code Review
This pull request introduces scoped configuration support to LogTape via the new withConfig() and withConfigSync() APIs, allowing temporary logging policies to be applied within specific execution contexts using context-local storage. The feedback suggests enhancing the robustness of resource disposal within these scopes by switching from ReadonlySet to mutable Sets for tracking filters and sinks, which prevents memory leaks and ensures disposal idempotency. Additionally, it is recommended to update the disposal helpers to delete items as they are processed, clear the sets in finally blocks, and wrap async disposal calls in try-catch blocks to safely handle synchronous errors.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b92e30e532
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Skip scoped resource disposal for sinks and filters still owned by an active parent logging scope. This keeps nested scopes that reuse a parent-owned disposable from closing it before the parent resumes. Add regression coverage for shared disposable sinks and filters across nested withConfig() calls. #188 (comment) Assisted-by: Codex:gpt-5.5
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces scoped configuration support to LogTape via the new withConfig() and withConfigSync() APIs, allowing temporary logging policies within specific execution contexts. The changes include the core implementation in scoped-config.ts, integration with the global configuration and logger, comprehensive test coverage, and updated documentation. The review feedback consistently recommends adding explicit type annotations for local variables, constants, and imports across the newly added code to clearly define intended types rather than relying solely on type inference.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
There was a problem hiding this comment.
Code Review
This pull request introduces scoped configuration support to LogTape, allowing users to temporarily override the process-wide logging policy within a specific execution context using withConfig() and withConfigSync(). The changes include the core implementation, extensive test coverage, and updated documentation. The review feedback highlights two important issues in scoped-config.ts where custom sinks or filters implementing both Symbol.asyncDispose and Symbol.dispose could be registered for both synchronous and asynchronous disposal, potentially leading to double-disposal errors. The reviewer suggests using else if blocks to ensure only one disposal method is registered.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2fc375ff46
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Track active scoped configurations so scope disposal can retain disposable sinks and filters still owned by another live scope. This prevents concurrent or overlapping scopes that share a resource from closing it while another scope can still route logs to it. Prefer Symbol.asyncDispose over Symbol.dispose when a scoped sink or filter implements both disposal protocols, matching async resource ownership with a single cleanup path. #188 (comment) #188 (comment) #188 (comment) Assisted-by: Codex:gpt-5.5
|
@codex review |
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces scoped configurations to LogTape, allowing temporary logging policies to be applied within specific execution contexts via withConfig() and withConfigSync(). The changes include compiling, running, and disposing of these scoped configurations, along with comprehensive tests and documentation updates. Feedback on the implementation highlights a potential race condition in getRetainedDisposables that could leak shared disposables, a recommendation to add robust input validation for logger configurations, and a suggestion to avoid mutating a Set during iteration in disposeSyncDisposables by copying it to an array first.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
|
Codex Review: Didn't find any major issues. More of your lovely PRs please. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Skip scoped configurations that are already disposing when collecting retained resources for another scope. This lets the still-running disposer finish the shared resource cleanup instead of leaking it through mutual retention. Validate scoped logger shapes before compiling them, so malformed runtime inputs raise ConfigError rather than incidental TypeError exceptions. Also copy sync disposable sets before iterating so cleanup does not mutate the set being traversed. #188 (comment) #188 (comment) #188 (comment) Assisted-by: Codex:gpt-5.5
|
@codex review |
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces scoped configuration support to LogTape, allowing temporary logging policies to be applied within specific execution contexts via withConfig() and withConfigSync(). It updates the documentation, exports the new APIs, and integrates them into the logger implementation and global configuration lifecycle. Feedback on the changes suggests adding validation for config.filters in compileScopedConfig to prevent potential runtime errors when non-object values are provided.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
|
Codex Review: Didn't find any major issues. Delightful! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Reject scoped configurations whose filters registry is present but not an object, so invalid user input fails with ConfigError instead of reaching Object.values() with a primitive value. #188 (comment) Assisted-by: Codex:gpt-5.5
|
@codex review |
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces scoped logging configurations to LogTape via the new withConfig() and withConfigSync() functions, allowing temporary logging policies to be applied within specific execution contexts using context-local storage. The feedback focuses on optimizing the performance of scoped record filtering in high-volume logging scenarios. Specifically, the reviewer suggests caching resolved filters for each category in a new filterCache map on CompiledScopedConfig and replacing JSON.stringify with manual string concatenation for category keys to minimize overhead in this critical hot path.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
|
Codex Review: Didn't find any major issues. 👍 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Cache the resolved scoped filter list per category so repeated log records avoid walking category prefixes on every emit. Keep the existing JSON-based category key so single segment categories containing separators do not collide with multi-segment categories. #188 (comment) #188 (comment) #188 (comment) Assisted-by: Codex:gpt-5.5
|
/gemini review |
|
@codex review |
There was a problem hiding this comment.
Code Review
This pull request introduces scoped configuration support to LogTape (version 2.3.0). It adds withConfig() and withConfigSync() functions, allowing users to apply temporary logging configurations within specific execution contexts using context-local storage. It also includes the ScopedConfig type, comprehensive tests, documentation, and updates to the developer guidelines. There are no review comments, so I have no feedback to provide.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
|
Codex Review: Didn't find any major issues. More of your lovely PRs please. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Closes #185.
Why
LogTape configuration is process-wide today, which makes short-lived logging policies awkward. Test helpers, diagnostics, and request-local capture often need a different set of sinks/filters for one execution flow without disturbing the application configuration.
This PR keeps the process-wide configuration as the source of runtime integration, especially
contextLocalStorage, and layers a scoped logging policy on top of the current execution context. That keeps the existing global model intact while giving callers a smaller primitive for temporary routing.How
The new API adds
withConfig(),withConfigSync(), andScopedConfigto@logtape/logtape. A scoped config uses the same sinks/filters/loggers shape asConfig, but leaves outresetandcontextLocalStorage. Callers configureConfig.contextLocalStorageglobally first, then use scoped configs for temporary logger routing.The scoped implementation lives in packages/logtape/src/scoped-config.ts. It compiles scoped logger state separately from the global logger graph, then logger dispatch checks the current scoped config before falling back to process-wide routing. The scoped path mirrors normal logger semantics, including
lowestLevel: null, parent sink inheritance, category prefixes, implicit context, and lazy evaluation.Filtering also follows the global dispatch order. A scoped logger first checks whether the record's level has an eligible dispatch plan, then runs filters only for records that can actually be emitted. That preserves the usual behavior for disabled levels and avoids running expensive or side-effectful filters for rejected records.
Scoped resources are disposed when the callback settles. Because context-local storage can propagate into async work that outlives the callback, disposed scoped configs are ignored by later propagated tasks. Those logs fall back to the nearest active parent scope, or to the process-wide configuration when no parent scope remains active.
Process-wide configuration changes are blocked while any scoped config is active, even from sibling async flows. That prevents
configure(),reset(), ordispose()from invalidating a still-running scope through shared global state.withConfigSync()follows the same lifetime model, but it rejects async disposable resources and promise-returning callbacks. The runtime callback guard observes rejected promises before throwingConfigError, so accidental async callbacks do not also produce unhandled promise rejections.Documentation and tests
The manual in docs/manual/config.md explains scoped configuration after the synchronous configuration section, including lifetime rules, nesting, interaction with
withContext()andwithCategoryPrefix(), global-onlygetConfig()behavior, meta logger setup, and disposal errors. CHANGES.md records the new 2.3 API.The regression coverage in packages/logtape/src/config.test.ts exercises nested and concurrent scopes, disposal, async propagation after disposal, sibling global mutations,
lowestLevel: null, disabled-level filters, invalid scoped configs, and sync callback/resource rejection.