Skip to content

[Python] Fix GRPC_TRACE not working when absl log initialized in cython#41814

Closed
sreenithi wants to merge 13 commits intogrpc:masterfrom
sreenithi:absl_init_log_fix_trace
Closed

[Python] Fix GRPC_TRACE not working when absl log initialized in cython#41814
sreenithi wants to merge 13 commits intogrpc:masterfrom
sreenithi:absl_init_log_fix_trace

Conversation

@sreenithi
Copy link
Copy Markdown
Contributor

@sreenithi sreenithi commented Mar 6, 2026

Follow up from #39779 that added the absl::InitializeLog() call in Cython. However this set the default STDERR level to error, hence disabling any GRPC_TRACE logs.

As discussed in abseil/abseil.github.io#467, the solution is to set the StderrThreshold to INFO to enable the GRPC_TRACE logs. This PR does the same.

In addition, a new test that checks for GRPC_TRACE logs is also added.

Related issue:

@sreenithi sreenithi added release notes: no Indicates if PR should not be in release notes and removed lang/Python labels Mar 6, 2026
@sreenithi
Copy link
Copy Markdown
Contributor Author

/gemini-review

@sergiitk
Copy link
Copy Markdown
Member

sergiitk commented Mar 7, 2026

/gemini review

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request correctly fixes an issue where GRPC_TRACE logs were being suppressed after absl::InitializeLog() was introduced. The approach of setting StderrThreshold to INFO before logger initialization is sound. The addition of a test case to verify GRPC_TRACE output is a great improvement. I have one suggestion to make this new test more robust by checking for specific log messages rather than a minimum line count, which can be brittle.

Comment thread src/python/grpcio_tests/tests/unit/_grpc_trace_log_test.py Outdated
@sergiitk sergiitk added release notes: yes Indicates if PR needs to be in release notes and removed release notes: no Indicates if PR should not be in release notes labels Mar 10, 2026
Comment thread src/python/grpcio_tests/tests/unit/_grpc_trace_log_test.py Outdated
Comment thread setup.py Outdated
Comment thread src/python/grpcio_tests/tests/unit/_grpc_trace_log_test.py Outdated
Comment thread src/python/grpcio_tests/tests/unit/_grpc_trace_log_test.py Outdated
Comment thread src/python/grpcio/grpc/_cython/_cygrpc/absl.pyx.pxi Outdated
Copy link
Copy Markdown
Member

@sergiitk sergiitk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you!

@sreenithi
Copy link
Copy Markdown
Contributor Author

Just for reference, posting the output of the test added in this PR to show that it actually fails without changes in #39779.

Test output using grpc==1.78.0 (without changes in #39779)

  • GRPC_TRACE logs testcase succeeds as expected
  • absl::Initialize warning test fails as expected
$ python tests/unit/_absl_log_test.py 
test_grpc_trace_log (__main__.AbslLogTest.test_grpc_trace_log) ... ok
test_no_absl_log_warning (__main__.AbslLogTest.test_no_absl_log_warning) ... FAIL

======================================================================
FAIL: test_no_absl_log_warning (__main__.AbslLogTest.test_no_absl_log_warning)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/local/google/home/ssreenithi/my_forks/grpc/src/python/grpcio_tests/tests/unit/_absl_log_test.py", line 54, in test_no_absl_log_warning
    self.assertFalse(absl_warning in self.output, f"absl::InitializeLog() warning unexpectedly found in output:\n{self.output}")
AssertionError: True is not false : absl::InitializeLog() warning unexpectedly found in output:
Channel created
WARNING: All log messages before absl::InitializeLog() is called are written to STDERR
I0000 00:00:1773133738.783809   53948 trace.cc:91] gRPC Tracers: api
I0000 00:00:1773133738.784107   53948 init.cc:132] grpc_init(void)
I0000 00:00:1773133738.784155   53948 completion_queue.cc:574] grpc_completion_queue_create_internal(completion_type=0, polling_type=0)
I0000 00:00:1773133738.784177   53948 completion_queue.cc:574] grpc_completion_queue_create_internal(completion_type=0, polling_type=0)
I0000 00:00:1773133738.784196   53948 channel_create.cc:249] grpc_channel_create(target=localhost:1234, creds=0x563727b7a0e0, args=0x7f50de7ba230)
I0000 00:00:1773133738.787388   53948 init.cc:132] grpc_init(void)
I0000 00:00:1773133738.787427   53948 transport_credentials.cc:33] grpc_channel_credentials_release(creds=0x563727b7a0e0)
I0000 00:00:1773133738.787569   53948 completion_queue.cc:1420] grpc_completion_queue_shutdown(cq=0x563727b4e460)
I0000 00:00:1773133738.787585   53948 completion_queue.cc:1426] grpc_completion_queue_destroy(cq=0x563727b4e460)
I0000 00:00:1773133738.787590   53948 completion_queue.cc:1420] grpc_completion_queue_shutdown(cq=0x563727b4e460)
I0000 00:00:1773133738.787595   53948 completion_queue.cc:1420] grpc_completion_queue_shutdown(cq=0x563727982b00)
I0000 00:00:1773133738.787600   53948 completion_queue.cc:1426] grpc_completion_queue_destroy(cq=0x563727982b00)
I0000 00:00:1773133738.787604   53948 completion_queue.cc:1420] grpc_completion_queue_shutdown(cq=0x563727982b00)
I0000 00:00:1773133738.787609   53948 channel.cc:95] grpc_channel_destroy(channel=0x563727b05c60)
I0000 00:00:1773133738.787620   53948 init.cc:166] grpc_shutdown(void)
I0000 00:00:1773133738.790839   53951 init.cc:166] grpc_shutdown(void)
I0000 00:00:1773133738.791195   53967 init.cc:154] grpc_shutdown_from_cleanup_thread


----------------------------------------------------------------------
Ran 2 tests in 0.447s

FAILED (failures=1)

Test output using grpc==1.78.1 (with changes in #39779)

  • GRPC_TRACE logs testcase fails as expected (regression)
  • absl::Initialize warning test succeeds as expected
$ python tests/unit/_absl_log_test.py 
test_grpc_trace_log (__main__.AbslLogTest.test_grpc_trace_log) ... FAIL
test_no_absl_log_warning (__main__.AbslLogTest.test_no_absl_log_warning) ... ok

======================================================================
FAIL: test_grpc_trace_log (__main__.AbslLogTest.test_grpc_trace_log)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/local/google/home/ssreenithi/my_forks/grpc/src/python/grpcio_tests/tests/unit/_absl_log_test.py", line 71, in test_grpc_trace_log
    self.assertTrue(
AssertionError: False is not true : Missing expected api trace(s) ['gRPC Tracers: api', 'grpc_init(', 'grpc_channel_create(', 'grpc_channel_destroy(', 'grpc_shutdown('], in output:
Channel created


----------------------------------------------------------------------
Ran 2 tests in 0.331s

FAILED (failures=1)

Test output with changes in this PR

  • GRPC_TRACE logs testcase passes
  • absl::Initialize warning test passes
$ python tests/unit/_absl_log_test.py 
test_grpc_trace_log (__main__.AbslLogTest.test_grpc_trace_log) ... ok
test_no_absl_log_warning (__main__.AbslLogTest.test_no_absl_log_warning) ... ok

----------------------------------------------------------------------
Ran 2 tests in 0.585s

OK

#
cdef _initialize_absl():
if not _disable_absl_init_log:
SetStderrThreshold(LogSeverityAtLeast.kInfo)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Todo: confirm if it should be called before or after InitializeLog()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good question. I checked it and it looks like there isn't a strict guideline for it. I searched across github and found examples doing both, however calling StdErrorThreshold before InitializeLog seems to be the pattern majority of the time.

Checking further with Gemini's help, here is the rationale behind that:

  1. Continuity: Before absl::InitializeLog() is called, the library is in a "pre-initialization" state where all log messages are directed to stderr by default, regardless of the threshold.
  2. Avoid a Logging Gap: Once absl::InitializeLog() is called, the library starts respecting the StderrThreshold (which defaults to kError). If you call InitializeLog() first, there will be a small window of time where INFO and WARNING logs are not sent to stderr until your subsequent call to SetStderrThreshold(absl::LogSeverityAtLeast::kInfo) completes.
  3. Correctness: Calling SetStderrThreshold() before InitializeLog() ensures that as soon as the library transitions to its initialized state, it is already configured with your desired threshold, resulting in a seamless transition.

From Point 2, I think in this particular case, it's actually fine because we have the calls happening one after another, but in future if we were to have some other code coming in between the calls, it's probably better to have the StdErrThreshold call before InitializeLog to avoid that gap.

@asheshvidyut
Copy link
Copy Markdown
Member

asheshvidyut commented Mar 11, 2026

Do we need default info or that too could be made configurable using env var?

Maybe we could honor GRPC_VERBOSITY.

@sreenithi
Copy link
Copy Markdown
Contributor Author

Do we need default info or that too could be made configurable using env var?

Maybe we could honor GRPC_VERBOSITY.

Thanks, good point. I also checked this after our discussion. First of all, GRPC_VERBOSITY is actually deprecated and we only want to support GRPC_TRACE which by default uses INFO level.

Secondly, for those who continue to use GRPC_VERBOSITY, they can still continue to use it as they already are. Setting to Info level here is not overriding that value. Just verified that by running the helloworld client by setting GRPC_VERBOSITY=error and GRPC_TRACE=api. Because verbosity is error, the trace logs shouldn't show up and that's what is happening, so I think we're good:

grpc/examples/python/helloworld$ GRPC_VERBOSITY=error GRPC_TRACE=api python greeter_client.py
Will try to greet world ...
Traceback (most recent call last):
  File "/usr/local/google/home/ssreenithi/my_forks/grpc/examples/python/helloworld/greeter_client.py", line 36, in <module>
    run()
  File "/usr/local/google/home/ssreenithi/my_forks/grpc/examples/python/helloworld/greeter_client.py", line 30, in run
    response = stub.SayHello(helloworld_pb2.HelloRequest(name="you"))
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/google/home/ssreenithi/.pyenv/versions/pyvenv_312/lib/python3.12/site-packages/grpc/_channel.py", line 1159, in __call__
    return _end_unary_response_blocking(state, call, False, None)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/google/home/ssreenithi/.pyenv/versions/pyvenv_312/lib/python3.12/site-packages/grpc/_channel.py", line 990, in _end_unary_response_blocking
    raise _InactiveRpcError(state)  # pytype: disable=not-instantiable
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with:
        status = StatusCode.UNAVAILABLE
        details = "failed to connect to all addresses; last error: UNKNOWN: ipv4:127.0.0.1:50051: Failed to connect to remote host: Connection refused"
        debug_error_string = "UNKNOWN:Error received from peer  {grpc_status:14, grpc_message:"failed to connect to all addresses; last error: UNKNOWN: ipv4:127.0.0.1:50051: Failed to connect to remote host: Connection refused"}"
>

@asheshvidyut
Copy link
Copy Markdown
Member

Abseil Default level is Error

https://github.com/abseil/abseil-cpp/blob/04f3bc01d12cf58c90a1bb68990f087fa3c3ed19/absl/log/globals_test.cc#L37-L39

If some other library, imports grpc, will they not get flooded with info level logs?

@sergiitk
Copy link
Copy Markdown
Member

Re: #41814 (comment): discussed IRL. We compile with -fvisibility=hidden, which ensures we have our private copies of absl symbols, with their own private global variables/state.

@sergiitk sergiitk changed the title [Python] Fix GRPC_TRACE and add test to check the GRPC_TRACE logs print [Python] Fix GRPC_TRACE not working when absl log initialized in cython Mar 17, 2026
Zgoda91 pushed a commit to Zgoda91/grpc that referenced this pull request Mar 22, 2026
…nt (grpc#41814)

Follow up from grpc#39779 that added the absl::InitializeLog() call in Cython. However this set the default STDERR level to error, hence disabling any GRPC_TRACE logs.

As discussed in abseil/abseil.github.io#467, the solution is to set the StderrThreshold to INFO to enable the GRPC_TRACE logs. This PR does the same.

In addition, a new test that checks for GRPC_TRACE logs is also added.

This PR also potentially fixes grpc#41696

Closes grpc#41814

COPYBARA_INTEGRATE_REVIEW=grpc#41814 from sreenithi:absl_init_log_fix_trace 0a8a9cb
PiperOrigin-RevId: 881977247
asheshvidyut pushed a commit to asheshvidyut/grpc that referenced this pull request Mar 26, 2026
…nt (grpc#41814)

Follow up from grpc#39779 that added the absl::InitializeLog() call in Cython. However this set the default STDERR level to error, hence disabling any GRPC_TRACE logs.

As discussed in abseil/abseil.github.io#467, the solution is to set the StderrThreshold to INFO to enable the GRPC_TRACE logs. This PR does the same.

In addition, a new test that checks for GRPC_TRACE logs is also added.

This PR also potentially fixes grpc#41696

Closes grpc#41814

COPYBARA_INTEGRATE_REVIEW=grpc#41814 from sreenithi:absl_init_log_fix_trace 0a8a9cb
PiperOrigin-RevId: 881977247
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bloat/none lang/Python release notes: yes Indicates if PR needs to be in release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants