This is an automated email from the ASF dual-hosted git repository.

jamesbognar pushed a commit to branch docs
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/docs by this push:
     new f2eba783fb REST debug 329 follow-ups: quick wins + revised specs
f2eba783fb is described below

commit f2eba783fb4d46911bb78194e6fbb41b848da9a4
Author: James Bognar <[email protected]>
AuthorDate: Sat Aug 15 18:49:04 2026 -0400

    REST debug 329 follow-ups: quick wins + revised specs
    
    - Implement READY-369 (capture caps + complete caching wrappers), READY-371 
(mixin op-logger naming/contract + tests), READY-373 (blast-radius 
migration/javadoc cleanup); archive to finished/.
    - Revise TODO-368 (JUL/Spring control plane), TODO-370 (secret-surface 
hardening; 2 review rounds), and split/revise TODO-372 into 372a/372b per 
adversarial cross-model review.
---
 .../topics/10.32.RestServerLoggingAndDebugging.md  | 54 ++++++++++++++++++++--
 pages/topics/27.V10MigrationGuide.md               | 34 +++++++++++++-
 2 files changed, 84 insertions(+), 4 deletions(-)

diff --git a/pages/topics/10.32.RestServerLoggingAndDebugging.md 
b/pages/topics/10.32.RestServerLoggingAndDebugging.md
index e0a4477fb5..a57f014ec2 100644
--- a/pages/topics/10.32.RestServerLoggingAndDebugging.md
+++ b/pages/topics/10.32.RestServerLoggingAndDebugging.md
@@ -22,9 +22,12 @@ that class's endpoints, at three cumulative tiers.
 
 Two JUL loggers are in play for any given request:
 
-- **Resource logger** — `Logger.getLogger(resourceClass.getName())`.
-- **Operation logger** — `Logger.getLogger(resourceClass.getName() + "." + 
methodName)`, once the request has been
-  routed to a specific `@RestOp` method.
+- **Resource logger** — the resource's *resolved* logger: 
`Logger.getLogger(resourceClass.getName())` by default,
+  or whatever a `@Bean`-annotated `RichLogger` factory method overrides it to 
(see
+  [Bean-overridden resource loggers](#bean-overridden-resource-loggers) below).
+- **Operation logger** — `Logger.getLogger(resourceLoggerName + "." + 
methodName)`, once the request has been
+  routed to a specific `@RestOp` method, where `resourceLoggerName` is the 
resolved resource logger's name from
+  above (i.e. the operation logger is always a JUL child of the *resolved* 
resource logger, override or not).
 
 Juneau resolves the *operation* logger first, falling back to the *resource* 
logger on unrouted/404 paths. Because
 this is a plain <a 
href="https://docs.oracle.com/en/java/javase/17/docs/api/java.logging/java/util/logging/Logger.html";
 target="_blank">java.util.logging.Logger</a>
@@ -45,6 +48,51 @@ With the configuration above:
 This is exactly the "set the resource logger to `FINE`, elevate one method to 
`FINEST`" pattern — per-operation
 control falls out of ordinary JUL inheritance, no Juneau-specific per-method 
attribute required.
 
+### Mixin operations resolve against the host
+
+An operation contributed by a composed 
[`@Rest(mixins=...)`](/docs/topics/RestServerMixinSubContexts) mixin uses
+the **host / top-level resource that composed the mixin** for its 
resource-logger portion — not the mixin class
+itself:
+
+```java
+public class EchoMixin { @RestGet(path="/echo/*") public ... echo(...) {...} }
+
+@Rest(mixins=EchoMixin.class)
+public class MyResource extends RestServlet {...}
+```
+
+Here the mixin-served `echo` operation's logger is named 
`com.example.MyResource.echo`, **not**
+`com.example.EchoMixin.echo`. Consequences:
+
+- Raising `com.example.MyResource`'s own JUL level cascades to `echo` (and 
every other mixin-served operation) —
+  ordinary JUL parent inheritance, same as any other operation on the host.
+- The same mixin class composed into two different host resources resolves to 
two independent, host-isolated
+  operation loggers (`HostA.echo` and `HostB.echo`) — raising one host's level 
never leaks into the other.
+
+### Bean-overridden resource loggers
+
+If a resource replaces its resolved logger via a `@Bean`-annotated 
`RichLogger` factory method:
+
+```java
+public class MyResource extends RestServlet {
+    @Bean
+    public RichLogger logger() {
+        return RichLogger.getLogger("my.app.custom.logger.name");
+    }
+}
+```
+
+every operation logger on that resource is named as a child of the 
*overridden* name
+(`my.app.custom.logger.name.<methodName>`), not the raw resource class name — 
so raising the overridden logger's
+level still cascades to its operations exactly as it would for the default, 
class-named logger.
+
+### 404 / unrouted requests
+
+When no operation is resolved (the request 404s, or otherwise never reaches a 
matched `@RestOp` method), Juneau
+falls back to the resource logger, but only ever emits the basic status-line 
summary — headers and bodies are
+never rendered on this path, no matter how high the resolved logger's level is 
set. Raising a resource to `FINEST`
+makes its *operations* log full detail; it does not retroactively add 
header/body detail to 404s.
+
 ## Tier table
 
 | Level | Content |
diff --git a/pages/topics/27.V10MigrationGuide.md 
b/pages/topics/27.V10MigrationGuide.md
index 995c2b7c76..6511824f63 100644
--- a/pages/topics/27.V10MigrationGuide.md
+++ b/pages/topics/27.V10MigrationGuide.md
@@ -116,7 +116,7 @@ Single-type imports follow the same rename, e.g.:
 | Class-level `@RestInit public void init(RestContext.Builder b) { ... }` hook 
— the framework added the in-flight `RestContext.Builder` to the resource's 
bean store so any `@RestInit` method that declared a `RestContext.Builder` 
parameter received it and could imperatively configure the resource-level 
context (`builder.path(...)`, `builder.children(...)`, `builder.encoders(...)`, 
etc.). | **Removed.** The class-level Builder-injection protocol is gone — 
`RestContext.Builder` is no longe [...]
 | Custom annotation appliers — user code that subclassed the internal 
`AnnotationApplier<Rest, RestContext.Builder>` (or `AnnotationApplier<RestOp, 
RestOpContext.Builder>`) to extend the annotation-processing pass (the 
`apply(AnnotationInfo<A>, B builder)` hook invoked once per annotation during 
context construction). | **Removed.** The builder-based apply-pass is gone; 
`RestAnnotation.Apply` (`RestContextApply`) is now a package-private nested 
class inside `RestContext` and is not exten [...]
 | Custom `RestAnnotation.create(...)` / `RestOpAnnotation.create(...)` 
builder-of-builders patterns — programmatic construction of `@Rest` / `@RestOp` 
annotation proxies used to feed synthetic annotations into the builder 
apply-pass (common in test fixtures and extension libraries). | The annotation 
proxy builders still exist for test use (`RestAnnotation.create()` / 
`RestOpAnnotation.create()` are still available via annotation-test helpers), 
but they no longer feed into a builder apply [...]
-| All prior REST debug/logging mechanisms, in order of vintage: `@Rest(debug)` 
/ `@RestOp(debug)` plain-string attributes; the nested `@Debug` annotation 
(`value()`/`on()`/`format()`/`level()`/`config()`) and its 
`debugDefault`/`debugEnablement`/`debugOn` siblings; 
`DebugEnablement`/`BasicDebugEnablement`/`DebugConfig`/`DebugRule`; and the 
`CallLogger`/`CallLoggerRule`/`BasicCallLogger` logging SPI (including the 
`juneau.restLogger.*` config keys). | **Removed — replaced by a single JUL  
[...]
+| All prior REST debug/logging mechanisms, in order of vintage: `@Rest(debug)` 
/ `@RestOp(debug)` plain-string attributes; the nested `@Debug` annotation 
(`value()`/`on()`/`format()`/`level()`/`config()`) and its 
`debugDefault`/`debugEnablement`/`debugOn` siblings; 
`DebugEnablement`/`BasicDebugEnablement`/`DebugConfig`/`DebugRule`; and the 
`CallLogger`/`CallLoggerRule`/`BasicCallLogger` logging SPI (including the 
`juneau.restLogger.*` config keys). | **Removed — replaced by a single JUL  
[...]
 
 ## REST Debug/Logging Redesign (JUL-Level-Driven `RestDebugFormatter`)
 
@@ -125,6 +125,21 @@ Juneau 10.0 replaces every prior REST debug/logging 
mechanism with a single sign
 [Logging / Debugging](/docs/topics/RestServerLoggingAndDebugging) for the full 
new model (level resolution, tier
 table, the `RestDebugFormatter` SPI, and secure-by-default redaction + body 
cap).
 
+:::danger `Enablement` was public 9.x API in the `juneau-marshall` core 
artifact — this is not just a rest-server-internal removal
+`org.apache.juneau.Enablement` (in 9.x; it would have been 
`org.apache.juneau.marshall.Enablement` under the 10.0
+"Marshall Package Rename" described earlier in this guide, had it survived) 
was a **released public enum** —
+`ALWAYS` / `CONDITIONAL` / `NEVER`, with `fromString(String)`,
+`isEnabled(boolean)`, and `isOneOf(Enablement...)` — shipped in the 
`juneau-marshall` core artifact, not a
+rest-server-only type. It has been **deleted with no replacement in 10.0**.
+
+- If you used `Enablement` **only** for `@Rest(debug=...)` / 
`@RestOp(debug=...)` (its sole in-framework consumer),
+  no action is needed beyond the debug/logging migration below — the JUL 
logger level replaces it entirely, and
+  there is no `CONDITIONAL`-equivalent (capture is derived from the logger's 
level, not evaluated per-request).
+- If your **own code** imported `Enablement` as a general-purpose tri-state 
enum unrelated to REST debug, define
+  your own replacement enum — Juneau 10.0 does not ship one. This is easy to 
miss because the class lived in a
+  core marshalling artifact most projects already depend on, not an opt-in 
rest-server module.
+:::
+
 | Removed | Replacement |
 |---|---|
 | `@Rest(debug=...)` / `@RestOp(debug=...)` and the nested `@Debug` annotation 
(`value()`, `on()`, `format()`, `level()`, `config()`) | No annotation 
replacement. Set your resource's JUL logger level (`INFO`/`FINE`/`FINEST`) 
instead. |
@@ -133,6 +148,23 @@ table, the `RestDebugFormatter` SPI, and secure-by-default 
redaction + body cap)
 | Config keys `juneau.restLogger.level` / `.enabled` / `.requestDetail` / 
`.responseDetail` / `.logger`, and `RestContext.debugDefault` | **Removed, no 
replacement.** The resource's own logger level is the only configuration 
surface. |
 | `RestContextArgs`-injectable `DebugEnablement` parameter type on `@RestOp` 
methods | **Removed, not replaced.** `DebugEnablement` is gone; there is no 
injectable equivalent. |
 
+### Per-operation logger naming (mixins and bean-overridden loggers)
+
+The per-operation logger name is `<hostLoggerName>.<methodName>`, where 
`hostLoggerName` is the **host** resource's
+*resolved* logger name (see [Logging / 
Debugging](/docs/topics/RestServerLoggingAndDebugging)) — not necessarily
+the raw resource class name:
+
+- **Mixins.** An operation contributed by a composed 
[`@Rest(mixins=...)`](/docs/topics/RestServerMixinSubContexts)
+  mixin resolves its logger name against the **host / top-level resource that 
composed the mixin**, not the mixin
+  class itself. Raising the host resource's own JUL level cascades to every 
mixin-served operation as a result, and
+  the same mixin class composed into two different hosts resolves to two 
independent, host-isolated operation
+  loggers — one per host.
+- **Bean-overridden resource loggers.** If a resource replaces its resolved 
logger via a `@Bean`-annotated
+  `RichLogger` factory method, the per-operation logger is a JUL child of that 
*overridden* name, not the raw
+  resource class name — so raising the overridden logger's level still 
cascades to its operations.
+- **404 / unrouted requests.** When no operation is resolved, only the basic 
status-line summary is ever logged;
+  headers and bodies are never rendered on this path, regardless of how high 
the resolved logger's level is set.
+
 :::warning Footgun: raising a logger's level for ordinary app logging also 
turns on REST capture
 Because the signal is the resource's **own** JUL logger, raising it to 
`FINE`/`FINEST` for reasons that have
 nothing to do with REST debugging — e.g. turning up verbose application 
logging on the resource class — **also**

Reply via email to