Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix logging #17064

Merged
merged 16 commits into from Nov 1, 2018
Merged

Fix logging #17064

merged 16 commits into from Nov 1, 2018

Conversation

gnossen
Copy link
Contributor

@gnossen gnossen commented Oct 31, 2018

This PR addresses both #17017 and #16572. In #16378, we add calls to logging.basicConfig() in various modules, which added a handler to the root logger.

One potential solution to the problem is to by default configure each module-level logger with a NullHandler. This does two things:

  • avoids the pesky "No handlers could be found" message
  • doesn't mess with the user's own logging

Without explicit configuration of a handler for the root logger in application code, this change will result in no logging output from grpcio. To address this issue for tests, I have added a call to logging.basicConfig() in all unit tests and test utilities I could identify. It's entirely possible I've missed some places.

@thelinuxfoundation
Copy link

Thank you for your pull request. Before we can look at your contribution, we need to ensure all contributors are covered by a Contributor License Agreement.

After the following items are addressed, please respond with a new comment here, and the automated system will re-verify.

Regards,
CLA GitHub bot

@gnossen
Copy link
Contributor Author

gnossen commented Oct 31, 2018

Agreed

@srini100 srini100 added lang/Python release notes: yes Indicates if PR needs to be in release notes labels Oct 31, 2018
Copy link
Contributor

@srini100 srini100 left a comment

Choose a reason for hiding this comment

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

Is it possible to add a test where app adds a handler and then imports grpcio. Would adding a NullHandler interfere with existing handler?

@grpc-testing
Copy link

Objective-C binary sizes
*****************STATIC******************
  New size                      Old size
 2,015,649      Total (=)      2,015,649

 No significant differences in binary sizes

***************FRAMEWORKS****************
  New size                      Old size
11,116,193      Total (<)     11,116,194

 No significant differences in binary sizes


@gnossen
Copy link
Contributor Author

gnossen commented Oct 31, 2018

@srini100 No, I don't believe so. Handlers are added to particular loggers. So if the user configured a particular grpc module to have a handler (which I doubt would happen very often), then logging.getLogger(__name__).addHandler(logging.NullHandler) is still okay. We'll simply be adding another handler, which from the experience of the user is a no-op.

As for the additional test, sure! Sounds like a good idea.

@grpc-testing
Copy link

Objective-C binary sizes
*****************STATIC******************
  New size                      Old size
 2,015,649      Total (=)      2,015,649

 No significant differences in binary sizes

***************FRAMEWORKS****************
  New size                      Old size
11,116,197      Total (>)     11,116,196

 No significant differences in binary sizes


@grpc-testing
Copy link

Objective-C binary sizes
*****************STATIC******************
  New size                      Old size
 2,015,649      Total (=)      2,015,649

 No significant differences in binary sizes

***************FRAMEWORKS****************
  New size                      Old size
11,116,198      Total (<)     11,116,201

 No significant differences in binary sizes


@gnossen gnossen changed the title WIP: Fix logging Fix logging Nov 1, 2018
@grpc-testing
Copy link

Objective-C binary sizes
*****************STATIC******************
  New size                      Old size
 2,015,649      Total (=)      2,015,649

 No significant differences in binary sizes

***************FRAMEWORKS****************
  New size                      Old size
11,116,194      Total (<)     11,116,195

 No significant differences in binary sizes


@grpc-testing
Copy link

Objective-C binary sizes
*****************STATIC******************
  New size                      Old size
 2,015,649      Total (=)      2,015,649

 No significant differences in binary sizes

***************FRAMEWORKS****************
  New size                      Old size
11,116,195      Total (>)     11,116,193

 No significant differences in binary sizes


@grpc-testing
Copy link

Objective-C binary sizes
*****************STATIC******************
  New size                      Old size
 2,015,649      Total (=)      2,015,649

 No significant differences in binary sizes

***************FRAMEWORKS****************
  New size                      Old size
11,116,187      Total (<)     11,116,197

 No significant differences in binary sizes


Copy link
Contributor

@lidizheng lidizheng left a comment

Choose a reason for hiding this comment

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

Looks great and discussed offline

class LoggingTest(unittest.TestCase):

def test_logger_not_occupied(self):
self.assertEqual(0, len(logging.getLogger().handlers))
Copy link
Contributor

Choose a reason for hiding this comment

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

Discussed offline that if this test case run after the other two test cases, it will always success since the logging module is reloaded.

reload_module(logging)
reload_module(grpc)
self.assertFalse(
"No handlers could be found" in sys.stderr.getvalue())
Copy link
Contributor

Choose a reason for hiding this comment

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

optional: There is assertNotIn function in unit test. https://docs.python.org/2/library/unittest.html#unittest.TestCase.assertNotIn

@grpc-testing
Copy link

Objective-C binary sizes
*****************STATIC******************
  New size                      Old size
 2,015,578      Total (=)      2,015,578

 No significant differences in binary sizes

***************FRAMEWORKS****************
  New size                      Old size
11,116,200      Total (>)     11,116,196

 No significant differences in binary sizes


@grpc-testing
Copy link

Objective-C binary sizes
*****************STATIC******************
  New size                      Old size
 2,015,578      Total (=)      2,015,578

 No significant differences in binary sizes

***************FRAMEWORKS****************
  New size                      Old size
11,116,194      Total (>)     11,116,192

 No significant differences in binary sizes


@grpc-testing
Copy link

Objective-C binary sizes
*****************STATIC******************
  New size                      Old size
 2,015,578      Total (=)      2,015,578

 No significant differences in binary sizes

***************FRAMEWORKS****************
  New size                      Old size
11,116,195      Total (>)     11,116,187

 No significant differences in binary sizes


@gnossen gnossen merged commit b741454 into grpc:master Nov 1, 2018
@gnossen gnossen deleted the fix-logging branch November 1, 2018 23:11
gnossen added a commit that referenced this pull request Nov 9, 2018
I was trying to get a feel for what the rest of the python ecosystem
does with its logging, so I looked into the top few libraries on pypi:

urllib3 maintains a logger for not quite every module, but for each
one that does heavy lifting. The logger name is `__name__`, and no
handlers are registered for any module-level loggers, including
NullHandler. Their documentation spells out how to configure logging
for the library.

They explicitly configure a library root-level logger called `urllib3`
to which they attach a `NullHandler`. This addresses the "no handlers
could be found" problem.

Their tests explicitly configure handlers, just like ours do.

scrapy is more hands-on. It provides a configuration module for its
logging and a whole document on how to handle logging with scrapy. It
looks like log.py's whole reason for existence is making sure that a
handler is attached to to the scrapy handler at startup.

I think the extra complexity here is because scrapy also offers a CLI,
so there has to be some way to configure logging without resorting to
writing python, so I felt we didn't need to resort to this added
complexity.

---

Based on all of the libraries I've looked at, I think our current
approach is reasonable. The one change I would make is to explicitly
configure a `grpc` logger and to only attach a `NullHandler` to it
instead of putting the burden on the author of each new module to
configure it there.

With this change, I have

- Configured a logger in each module that cares about logging
- Removed all NullHandlers attached to module-level loggers
- Explicitly configured a `grpc` logger with a `NullHandler` attached

Resolves: #16572
Related: #17064
@lock lock bot locked as resolved and limited conversation to collaborators Jan 30, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
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.

None yet

6 participants