-
Notifications
You must be signed in to change notification settings - Fork 36
fix: Remove Thread/event to fix Django regression #107
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
Conversation
b42770e to
f0306ef
Compare
|
|
||
|
|
||
| class LogDNAHandlerTest(unittest.TestCase): | ||
| def setUp(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most of the changes in this class are due to the removal of the setup / teardown of the unit test class instance of the handler. This is no longer necessary since we are removing the creation of the flusher thread from the lifecycle of the class itself. It also is inconvenient since it gets in the way of some of the mock patching that is used in the unit tests.
f0306ef to
84dc703
Compare
having multiple instances of LogDNAHandler is valid use case. why close() can be hanging? does not look like a "graceful" close(). |
That issue is resolved with this PR. The issue is a little more complicated then just that there are multiple handlers. It's not a static issue, so much as it's a state issue, and there are interesting things happening under the hood when Django instantiates loggers and other objects and then manages the life-cycles of the instances. The reason this was a problem with the previous implementation is because the previous implementation would instantiate a thread upon instantiation of the class, in the constructor, and then would shut this thread down via an event mechanism when the handler's Because of what Django is doing under the hood, the handlers are instantiated and then provided as dependencies to the relevant code using Django's dependency injection. This causes issues when some of these handlers have threads that are running. Django will "hang" during startup as it is waiting for certain threads to exit, despite the fact that these threads are marked as daemon threads and thus should not cause applications to wait on their state. This may be in issue for Django and libraries like it because of object de/serialization that happens as dependencies are created and then injected as dependencies. This PR effectively addresses this by not trying the lifecycle of a thread to class instantiation. |
|
|
||
| def close(self): | ||
| # Close the flusher | ||
| self.close_flusher() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
close_flusher & start_flusher are called under lock except this place.
harmless?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be, yes, because close is only called by the python logging library when the application closes. Further, closing / cancelling the flusher is a no-op if the flush timer thread has already started.
dkhokhlov
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
a8ba70e to
2b2a317
Compare
Re-opening #106 in order to make sure these are merged properly and separately. These were prematurely merged into a separate user branch, rather than into master.
Due to the nature in which some third party libraries / frameworks (such as Django) will instantiate and close loggers multiple times between application startup / shutdown, revert a small portion of the recent changes to return to the pattern where the flusher can be started / stopped, based on the condition of the buffer and whether or not there is buffered data. This has been tested against the previous data loss issue and is verified to still ensure that 100% of buffered data is synced.
This change can be broken down into the following functional elements:
close()method hanging while the flush thread spins endlessly, despite the fact that it is a daemon thread.