Skip to content

examples: add a Log4j 2 logging context example - #13057

Open
AgraVator wants to merge 2 commits into
grpc:masterfrom
AgraVator:log4j2-example
Open

AgraVator wants to merge 2 commits into
grpc:masterfrom
AgraVator:log4j2-example

Conversation

@AgraVator

Copy link
Copy Markdown
Contributor

Adds example-log4j2, showing how a server interceptor can put per-call values into the Log4j 2 ThreadContext so they end up on every log line the service writes. Logging frameworks read from thread-local storage rather than io.grpc.Context, so the interceptor has to set the values on whichever thread runs each callback.

2026/09/14 09:10:54:450 UTC INFO  CustomLogServer - Server started, listening on 50051
2026/09/14 09:11:02:679 UTC INFO  CustomLogServer - Got a request {requestId=4da3d1d9-47b6-46b7-876d-8af1b16f65dd, clientName=my.domain.name}

This revives #5835 by @carl-mastrangelo, which was reviewed but never merged; the example is his. It picks up the review comments that were left open there: the directory is named example-log4j2 so the Kokoro loop finds it, the BUILD.bazel copied from the ALTS example and the vendored gradle wrapper are gone, the README says what the example is for and names the right scripts, and the versions are current.

It also sets the context around next.startCall(), not just in the listener callbacks, so interceptors further down the chain see it too. That was the gap @Nipel-Crumple raised on #5835.

The server uses LogManager and a log4j2.xml with %X in the pattern instead of building a SimpleLogger by hand, since that's what a reader would actually copy.

Add example-log4j2, showing how a server interceptor can put per-call
values into the Log4j 2 ThreadContext so that they are appended to every
log statement the service makes. This is the non-io.grpc.Context scoped
case, since logging frameworks read from thread-local storage.

The server uses LogManager plus a log4j2.xml whose pattern includes %X,
rather than constructing an internal SimpleLogger by hand, so the
contextual values are actually visible in the output.

Supersedes grpc#5835, which was reviewed but went stale. Relative to that
change: the directory is example-log4j2 rather than examples-log4j2 so
that the loop over examples/example-* in buildscripts/kokoro/unix.sh
picks it up; the BUILD.bazel copied from the ALTS example and the
vendored gradlew files are dropped; the README explains what the example
illustrates and names the scripts the build actually produces; and the
gRPC, protoc and Log4j 2 versions are current.
Establish the ThreadContext around next.startCall() as well as in the
listener callbacks, so that interceptors further down the chain see the
values while their own interceptCall() runs. This was raised on grpc#5835 and
left unresolved there.

Also resolve the client's host name once instead of on every RPC, bump
Log4j 2 to 2.26.1, and correct the log4j2.xml comment, which described a
bare %X rather than the explicit keys the pattern actually uses.
@AgraVator
AgraVator marked this pull request as ready for review September 14, 2026 09:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant